这里教大家在TCP基础上设计属于自己的通讯协议。
首先TCP是可靠连接,丢包是重发的,数据是严格的顺序发送,客户端的发送顺序就是服务端的接收顺序。
自定义通讯协议草稿:[论坛上所谓的“粘包”都是不懂通讯协议设计的同学]
1。这是文件传输协议。是基于TCP的文件传输协议,所有协议头数据使用简体中文。
2。协议分两个部分,协议头和数据本身。协议头和协议使用两个换行符分割。
3。协议头规定。协议头分多行文本,每一行一个参数,每一行结尾用换行符分割。
4。第一行核心命令行,包括2个,发送+空格+文件名字,或者,接收+空格+文件名字。
5。第二行长整数文本,表示文件的总长度。
6、第三行长整数文本,起始位置,从0开始、比如100字节的文件起始位置结束位置分别为 0-99
7、第四行长整数文本,结束位置,从0开始、比如100字节的文件起始位置结束位置分别为 0-99
8、第五行长整数文本,当前数据段长度,允许0字节。0字节咋数据段为空。
备注:当前数据段长度等于 结束位置-起始位置+1  比如起始位置结束位置分别为 0-99 数段长度就是 99-0+1=100
备注:协议头和后面数据用两个换行符分割。
备注:起始位置结束位置都是0 表示从取当前位置1字节的信息。数据长度是 0-0+1 =1个字节。
9、协议头+两个换行符+当前数据库段。数据段长度必须在第五行说明,数据段后是新的协议包的第一行。
备注:协议头+两个换行符+当前数据库段+协议头+两个换行符+当前数据库段+协议头+两个换行符+当前数据库段...
10、客户端的发送等于服务端的接收,服务端的接收等于客户的发送,客户端服务端平衡权限相互问答传输。
11、只有完成当前数据段发送/接收以后,才能启动一个新的数据段发送。同一连接同时时刻只能有一个数据段正在传输。
12、当客户端使用发送命令,服务端处于接收状态,当客户端使用接收命令,服务端发送相应数据。
13、当服务端使用发送命令,客户端处于接收状态,当服务端使用接收命令,客户端发送响应数据。
14、传输使用轮询方式,如果,客户端发送第一个包,完成后,服务端发送第二个包。反之亦然。这里规定了传输控制方式。
15、如遇到数据段重复等异常情况,允许接收方断开连接。
16、如果客户端被断开,则立刻放弃当前数据包传输,主动尝试连接服务器,并被动等待第一个数据包。
17、如果服务端被断开,服务端停止当前任务等待新的连接。
所有数据传输基于TCP,发送的数据包必须大于24字节并小于1G,接收数据包后首先顺序组包,然后解析协议头并接收数据。
等等...
自己扩展吧,这个是抛砖引玉。

举例补充:
比如,客户端首先主动  发送 0-99  服务端接收了, 如果成功了 改为服务端主动,就来个  接收 100-199 客户端收到后就发送100-199的数据。
如果第一包失败了,服务端就来个 接收 0-99  客户端收到后,就重发0-99
如果服务端 接收客户端第一个数据后, 响应的不是 接收命令,而是发送,那么角色对调了。
客户端就不能发了,改为接收,服务端改为发送。传输方式改变。

传输协议,需要解决两个问题,第一个是语法是什么,就是数据怎么发,格式是什么,
然后就是怎么进行交流和对话,就是话语权怎么控制,

比如http就是永远客户端主动服务端被动,这就是控制权的处理,文件传输,是轮询方式居多,上面我们设计的就是轮询方式。
如果把上面的 发送命令,理解为提问,把接收命令理解为应答。
那么上面的协议,就是轮流提问,每个人问一次。两个人是平等的。

http协议就不同,http永远是客户端提问,服务端应答,这就是控制方式的设计问题。
这两种方式各有优点缺点,这里不讨论。


常见错误第一个:[这就是所谓的粘包的由来,其实是个错误]
很多人喜欢利用分包大小来设计协议,这个是错的。
客户端发送快速两个10字节的小包,服务端可能只收到一个20字节的大包。
客户端发送一个超级大的数据包,服务端可能会是几十个小的分包依次到达。
所以根据分包的大小来判断数据是非常不可靠的,必须设计相关通讯协议。
扩展说明:
标准的tcp只有两种情况,发送成功了,或者没发送成功,不存在丢包问题,tcp内部有机制,丢包是重发的。
有些TCP客户端或服务端,处理缓存有问题,比如,把数据放到缓存,没发送完成,就放入新数据,导致一些数据覆盖丢失。
或者发送缓存使用中会导致发送命令失败,很多人没注意发送命令的偶尔失败,导致一些数据没有发出。丢了数据。
常见错误第二个:
很多人收到一个数据包后立刻启动一个线程去处理这个包,当收到第二个包,就启动一个新的线程去处理,
这样很快就会有大量的线程或快或慢的处理一些并不很大的数据,而且非常容易导致线程顺序颠倒组装数据困难。甚至丢包。
正确的做法是,依次接收数据,当数据缓存到一定数量再启动线程去处理,每一个线程处理是哪段数据有多大要有控制。
比如迅雷的接收缓存就可以高达16M。
常见错误第三个:
很多人发送硬盘上的数据喜欢载入内存,比如文件有1G大,如果有100个同时下载,内存会怎样,有那么多内存么?程序会死掉。
网络传输层,为什么都要分很多小的数据包发送,就是为了减少服务端消耗,同时提高并发处理能力,这是非常必要的。
计算机速度很快,数据包的多少不是太大的问题,可以很快的执行,但是如果每个包就特别大,就会导致其他用户等待,并发能力就差了。
所以TCP的发送和接收都是小包快发,如果你理解了这些,就不会把上G的数据直接读到内存然后发送了。而且:
很多时候减少内存的使用波动,减少内存的申请和释放次数是可以有效提高程序效率的,自己理解吧。