题目要求:用udp协议模仿tcp协议实现一个文件传输软件
题目只要求单向传输就可以,比如说A-->B。就是一个发,一个收,其实如果是真正的tcp协议的话是双向的,通信双方既可发也可收。但是道理是一样的,不过变换了一下主体而已。
具体操作是把一个文本文件按一定大小进行切分,然后通过udp协议发送出去。因为udp协议是不可靠的,只管发,接收方有没有收到它可不管。所以题目要求就是在udp的基础上模拟tcp协议实现一个可靠的文件传输软件。
关键点分析:
要进行文件传输,首先就要建立连接,要建立传输首先就要有一方主动发起连接请求,另一方被动接受连接请求。一般我们称发起方为客户端,被动接受方为服务器。就跟我们的网页浏览一样,浏览器是客户端,而给浏览器传回网页的是服务器。建立连接请求就可以借鉴参考TCP协议中的3次握手。
首先是客户端向服务器发送一个请求报文SYNC,服务器接受到请求报文后给客户端返回一个ACK报文,也是就确认收到客户端请求。同时在ACK报文中附加一个SYNC标志,相当于服务器端也向客户端发送连接请求,我们简称为SYNC+ACK,或者更准确的是ACK+SYNC。因为更重要的是确认收到客户端请求,再次是服务器方发出SYNC连接请求。只是因为没有什么别的事情需要等待,而ACK和SYNC是每个tcp报文头部中都包含的标志位,所以把ACK报文和SYNC报文放在同一个报文中一次发送出去,节省时间和带宽。请求的意思就是请求另一方做好接收准备,我有数据要传给你了。最后客户端收到服务器方发送的SYNC+ACK报文包,也返回一个ACK确认报文给服务器,因此双方都知道对方已准备就绪,到这里就算连接建立了。
因为tcp传输是双向的,其实这过程中是通信双方说了4句话,叫做“有来有往”。只不过第二第三句放在一句话了说了,所以简称3次握手,其实本质上是2句对话,首先客户端告诉服务器,“我有数据要传输给你,请你做好准备!”,服务器回答,“OK,I’m
ready。随时恭候大驾,”同时服务器也告诉客户端,“我也有数据要发给你,也请你准备好!”只不过一句话就说完了,可以简写“OK,the
same as you ?”。
结束传输过程(简称分手,4次挥手)
其实3次握手和4次挥手是一样的道理,因为徐志摩曾写过“我挥一挥手,不带走一片云彩”,所以挥手也是分手的行礼而已。只不过因为分手时双方都显得慎重,所以说话也是规规矩矩的,始乱终弃是万万不能的!前面开始交往时大家都是迫不及待,所以说话也是两句并作一句说,两部并作一步走。这跟恋爱双方的情况是何其相似。都是双方相互请求,不过是此一时彼一时。
前面说了来路退路,现在来说实际传输过程,前面两部分都是为了保证可靠的传输。传输过程说复杂也复杂,说简单也简单,只要保证正确无误,实时高效就行了。
说复杂是针对实际Internet来说,网络环境复杂,什么情况都可能发生,丢包,延时,出错。所以TCP当中就有了很多的机制来保证达到可靠传输的要求。说简单是因为题目中标准版只要我们处理丢包,而且丢包不是实际网络造成的,因为测试是在一个局域网中,丢包的概率几乎为零。而是要由程序本身来模拟,就是用一个随机数发生器,如果产生的随机数大于某个设定值就正常把数据包发送出去,如果小于就不发送,对于接收端来说就相当于是丢包。
而处理丢包最简单的方法就是重发,我们可以给每个数据包标上单独的序号,参考tcp头部中的序号,然后要求接受端对收到的每个数据包返回确认函(ACK报文)。如果在一定发出一定时间后还没收到相应的确认函就重发。
这是题目要求,其实也可以有另一种处理方法,一开始传输时就告诉接收方有多少个数据包,然后在发送方首次把全部数据包发送完成后给接收方发送一个请求确认收讫报文。接收方在收到请求收讫报文后对全部接收到的数据进行检查确认,看是否全部接收完整。如果某些包丢失,就发送包含丢失报文序号的请求重发报文,发送方收到接收方的请求重发报文后就重发相应报文,然后再次给接收方发送请求确认收讫报文,直到接收到接收端的收讫报文。然后然后就可以关断连接,这样就节省了接收方每次收到数据包都要返回ACK确认函的开销,也提高了效率。
(4)设计协议头部
对照tcp头部,我们知道,要实现可靠传输,报文序号和确认号必须要有。其实这两个字段主要是解决两个问题,网络延时和丢包。因为如果没有序号,发出去100个数据包,因为网络延时问题,接收端不是按顺序收到,这时就会乱套了。还有丢包问题,如果没有确认号,发出去100,接受端只收到50个?那怎么处理呢?最直接的是要求接收端对收到的每个报文返回确认号,发送端没有收到确认号的就相当于是丢包了,直接重发就行了。
所以头部中序号和确认号是必不可少的。
因此我们可以根据题目要求实现一个简化版的tcp协议,只是针对题目中的文件传输,那我们可以用10个字节表示头部就行了。如下所表示
1B(命令码SYNC/ACK/FIN)+4B(序号)+4B(确认号)+1B(保留,可做校验)
首个字节中我们可以之需要用到3个bit就行了,因为在我们题目中只需用到这3个标志位。
3.实现步骤
首先必须练习使用tdp相关socket编程api,可以从网上下载一个网络调试助手,暂时充当发送方和接收端。
熟练udp相关操作后就分别编写接收端发送方,然后互传字符数据,进行测试。调试没问题后就用一个文件来进行测试,发送方根据一定大小切分文件,然后发送给接收端,接收端再根据序号恢复成一个完整的文本文件。你只需在自己电脑上调试就行了,这时不需考虑丢包等问题。只用用localhost或127.0.0.1就行了,然后通过不同端口号区分。
等你上面完全调试好后就添加一个随机数模块来模拟丢包问题,你首先确定一个数,比如说0.5,当产生的随机数大约0.5时你就正常发送相关包,小于0.5时就不发送,这就相当于丢包了,通过这个来调试重发机制功能。