socket传输协议
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
竭诚为您提供优质文档/双击可除
socket传输协议
篇一:socket开发之通讯协议及处理
socket开发之通讯协议及处理
在socket应用开发中,还有一个话题是讨论的比较多的,那就是数据接收后如何处理的问题。这也是一个令刚接触socket开发的人很头疼的问题。
因为socket的tcp通讯中有一个“粘包”的现象,既:大多数时候发送端多次发送的小数据包会被连在一起被接收端同时接收到,多个小包被组成一个大包被接收。有时候一个大数据包又会被拆成多个小数据包发送。这样就存在一个将数据包拆分和重新组合的问题。那么如何去处理这个问题呢?这就是我今天要讲的通讯协议。
所谓的协议就是通讯双方协商并制定好要传送的数据的结构与格式。并按制定好的格式去组合与分析数据。从而使数据得以被准确的理解和处理。
那么我们如何去制定通讯协议呢?很简单,就是指定数
据中各个字节所代表的意义。比如说:第一位代表封包头,第二位代表封类型,第三、四位代表封包的数据长度。然后后面是实际的数据内容。
如下面这个例子:
前面三部分称之为封包头,它的长度是固定的,
第四部分是封包数据,
它的长度是不固定的,由第三部分标识其长度。因为我们的协议将用在tcp中,所以我没有加入校验位。原因是tcp 可以保证数据的完整性。校验位是没有必要存在的。
接下来我们要为这个数据封包声明一个类来封装它:
1publicclassmessage
2{
3privatebyte_class;
4privatebyte_flag;
5privateint_size;
6privatebyte[]_content;
7
91011{get{return_content;}set{_content=value;}12}13 14publicintsize151617{get{return_size;}set{_size=va lue;}18}
19
20publicbyteFlag
21
22
23{get{return_flag;}set{_flag=value;}
24}
25
26publicbyteclass
27
28
29{get{return_class;}set{_class=value;}
30}
31
32publicmessage()
33
34
35}
36
37publicmessage(byte@class,byteflag,byte[]content) 38{{
39_class=@class;
40_flag=flag;
41_size=content.length;
42_content=content;
43}
44
46{47byte[]_byte;48using(memorystreammem=newmemorys tream())49{50binarywriterwriter=newbinarywriter(mem );51writer.write(_class);52writer.write(_flag);53wr iter.write(_size);54if(_size>0)
55{
56writer.write(_content);
57}
58_byte=mem.toarray();
59writer.close();
60}
61return_byte;
62}
63
64publicstaticmessageFrombytes(byte[]buffer)
65{
66messagemessage=newmessage();
67using(memorystreammem=newmemorystream(buffer))
68{
69binaryReaderreader=newbinaryReader(mem);
70message._class=reader.Readbyte();
71message._flag=reader.Readbyte();
72message._size=reader.Readint32();
73if(message._size>0)
74{
75message._content=reader.Readbytes(message._size); 76}
77reader.close();
78}
79returnmessage;
80}
8182
}我们可以用tobytes()和Frombytes()将封包转换成二进制数组和从二进制数组转换回来。事情看起来已经解决了,但真的是这样子吗?不然,我们知道,tcp数据是以流的形
式被传送的,我们并不知道一个数据包是否被传送完毕,也不知道我们接收回来的数据包中是否有多个数据包,如果直接使用Frombytes()来转换的话,很可能会因为数据不完整
而出现异常,也有可能会因为数据中含有多个数据包而导致
数据丢失(因为你并不知道这些数据中含有多少个数据包)。那我们该怎么办?这也不难,我们先把接收回来的数据写入一个流中。然后分析其中是否有完整的数据包,如果有,将其从流中取出,并将这部分数据从流中清除。直到流中没有完整的数据为止,以后接收回来的数据就将其写入流的结尾处,并从头继续分析。直到结束。
让我们来看看这部分的代码:
1publicclassmessagestream
2{
3privatebyte[]_buffer;
4privateint_position;
5privateint_length;
6privateint_capacity;
7
8publicmessagestream()
9{
10_buffer=newbyte[0];
11_position=0;
12_length=0;
13_capacity=0;
14}
15