android 自定义socket(二) ---数据传输

先上github地址:https://github.com/szd201208/PuddingSocket/tree/master

以下直接贴相关代码。

1.获取socket数据流

Socket socket=new Socket();
socket.connect(new InetSocketAddress(host, port));
           InputStream mSocketInputStream = socket.getInputStream();
            OutputStream mSocketOutputStream = socket.getOutputStream();

维护消息队列

LinkedBlockingDeque<String> mWriteBlockingQueue = new LinkedBlockingDeque<>();

2.数据形式为字符串

发送

 String queueMessage = mWriteBlockingQueue.take();
                        if (queueMessage != null) {
                            Log.e(TAG, "write ---> " + queueMessage);
                     mSocketOutputStream.write(String.valueOf(queueMessage+"\r\n").getBytes());
                            mSocketOutputStream.flush();
                        }

接收

 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(mSocketInputStream));
                    String readlineStr = bufferedReader.readLine();

分析:数据格式为字符串时,我们可以使用Io自带的readLine方法来读取单条数据,但readLine的时候,我们需要在已有字符串后面手动添加\r,\n或者\r\n。

readLine的相关源码如下:

image.png

这样就会导致一个问题,当我们的字符串中有\r,\n或\r\n相关字段时,一条消息就会被裁切成多条消息。

3.数据形式为byte数组

如果发送的内容不是字符串,而是一个文件,一张图片或者一段语音呢?按照上面的思路,我们有两种处理方案:当我们发送非字符串内容时,可以先调用接口发送文件至后台,当后端返回相关url之后,我们就可以将url拼接到相关字符串里,之后按照上面的方式来发送字符串数据;第二个方案就是直接发送byte数组,因为后端调接口发送文件的实质也是发送byte数组。以下我们着重就第二种方案进行分析。
因为tcp会有粘包和拆包出现,那么我们又是怎么判定一条消息的完整性呢?

基本思路就是前后端约定好byte数组的格式,比如我们约定好每一条完整的消息包含包头+包体,其中包体为消息实体的byte数组格式(1),包头为(1)中数组长度l所对应的byte数组,长度暂定为4(2),完整消息的byte数组=(1)+(2)。

以字符串为例,在LinkedBlockingDeque中,我们可以维护一个SocketMessage。


image.png

消息发送

                        if (queueMessage != null) {
                            Log.e(TAG, "write ---> " + queueMessage);
                            byte[] result = queueMessage.getResult();
                            mSocketOutputStream.write(result);
                            mSocketOutputStream.flush();
                        }

消息接收

byte[] resultLength = getBytesWithLength(inputStream, 4); 
                        if (resultLength != null) {
                            int length = big_bytesToInt(resultLength); //byte[]转为int
//从inputStream获取length个字节内容,即为消息实体
                            resultBytes = getBytesWithLength(inputStream, length);
                            if (resultBytes != null) {
                                    String res = new String(resultBytes);  //byte[]转为String
}
}

4.拓展

以上发送byte数组我们是以字符串为例,那么如果我们同时需要发送String,图片,视频,音频等内容,SocketMessage我们又该如何定义呢?

欢迎评论区技术探讨。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
禁止转载,如需转载请通过简信或评论联系作者。

相关阅读更多精彩内容

友情链接更多精彩内容