综合课程设计报告
基于TCP协议的文件传输系统
学生姓名:
指导教师:
所 在 系:
所学专业:
年 级:
2011年 6月
目 录
摘要………………………………………………………………………………………2
1、实验的相关知识 .......................................................3
1.1、通信的模式..........................................................3
1.1.1、传输的可靠性......................................................3
1.2.1、TCP/IP的网络体系结构..............................................3
1.2.2、TCP/IP网络协议 ...................................................4
1.2.3、TCP——传输控制协议...............................................4
2、winsock控件 .........................................................5
2.1.1、winsock的重要属性、方法和事件.....................................5
2.1.2、winsock控件通信的工作原理.........................................7
3、程序设计与实现.........................................................8
3.1、程序设计.............................................................8
3.1.1、总体设计...........................................................8
3.1.2、模块设计...........................................................9
3.2、程序实现.............................................................10
3.2.1、工作原理...........................................................10
3.2.2、服务器端主程序.....................................................11
3.2.3、客户端主程序.......................................................14
4、实验总结...............................................................17
参考文献...............................................................17.
成绩评定................................................................18
基于TCP协议的文件传输系统
摘 要
随着网络的普及,网络编程显得尤其重要。本实验使用Winsock控件实现两台计算机间的文件传输,描述了Winsock控件的使用方法及有关文件传输的算法。 随着计算机网络的迅速发展,人们的生活越来越离不开网络,如今网络编程已成为计算机发展的热点,而在众多的网络通信中,又以TCP/IP协议最为流行。本文讨论的Winsock控件,提供了访问TCP/IP网络的捷径,使用它可以不必了解TCP/IP的细节和调用Winsock API,只要设置好相应的属性和触发事件后的处理,就可以实现计算机之间的数据通信,进行文件传输了。同时为了便于传输文件过程中的中断现象,在实验时应该充分考虑断点续传问题,即中断文件传输后已经传输的文件不丢失,等到再传时,能继续接着传送。
关键词 :TCP/IP协议,Winsock控件,网络编程,文件传输,断点续传。
1、 实验的相关知识
1.1通信的模式
由于是实现点对点的文件传输,因此在程序中我们使用的是C/S的模式来实现通信。对于C/S的模式,即分为客户端和服务端。服务端用来接收客户端的连接,实现两端之间互相传输文件。采用C/S的模式可以更好的体现程序的功能设计思想,充分调用在LAN中的server和client两方面的处理能力,极大的减少网络上的信息流通量。C/S体系结构有可能提供一种开放式的、易伸缩扩展的分布式计算机环境,并保护硬件等投资。
1.1.1 传输的可靠性
要想实现文件的可靠性传输,可以使用流式套接字。因为流式套接字提供面向连接的、无差错的、发送顺序一致的、包长度不限和非重复的网络信息的传输,能提供更好的可靠性。而对于数据报套接字提供的是无连接的服务,以独立的数据报进行传输,不保证顺序性、可靠性和无重复性,相比之下用流式套接字能提供更好的的可靠性传输。
1、2、1TCP/IP的网络体系结构
TCP/IP协议采用层次体系结构,如图1所示,从图中可以看出,每一层在逻辑上都与通信端的对应层相连接。图中所示的服务器程序持续监听通信客户端;客户端仅周期性地与服务器相连接以交换数据,其中TCP协议层提供相当于OSI参考模型中传输层的服务,为收、发端应用程序提供通信;IP协议层负责提供统一的数据报;链路层主要功能是收、发IP层的IP数据报;TCP/IP之上是该协议提供的各种服务,而底层网络可以是不同的物理网络,如Ethernet、Token Ring、X.25公共分组交换网等。
图1 TCP/IP协议层模型(LAN)
1、2、2 TCP/IP网络协议
协议是对等的网络实体之间通信的规则,可以简单地理解为网络上各计算机彼此交流的一种“语言”。网络通信协议设计的基本原则是层次化,层和协议的集合被称为网络体系结构。相邻层之间的接口定义了下层向上层提供的基本操作和服务,下层向上层提供的服务分两种形式:面向连接的服务和无连接的服务。
计算机网络中已经形成的网络体系结构主要有两个:OSI参考模型和TCP/IP参考模型。TCP/IP参考模型是因特网(Internet)的基础。和OSI的7层协议相比,TCP/IP协议只有4个层次。通常说的TCP/IP是一组协议的总称,TCP/IP实际上是一个协议族,包括100多个相互关联的协议,其中IP(Internet Protocol, 网际协议)是网络层最主要的协议;TCP(Transmission Control Protocol,传输控制协议)和UDP(User Datagram Protocol,用户数据报协议是传输层中最主要的协议),一般认为IP、TCP、UDP是最根本的三种协议,是其他协议的基础。
1.2.3 TCP——传输控制协议
面向连接的通信可以使用可靠通信,在这时候,第四层协议发送数据接收方的确认,如果未收到数据或者数据被损坏,则请求重新传输。TCP协议就使用这种可靠通信。使用TCP协议的应用层协议包括HTTP、FTP、SMTP和Telnet等。
TCP要求在发送数据之前必须打开连接。服务器应用程序必须执行一个称作被动打开(passive open)的操作,以利用一个已知的端口号创建一个链接,这是,服务器并不是对网络进行呼叫,而是侦听并等待引入的请求。客户应用程序必须执行一个主动打开(active open),为此,它向服务器应用程序发送一个同步序列号(SYN)以标识连接。客户应用程序可以将动态端口号作为本地端口使用。服务器必须向客户发送一个确认(ACK)以及服务器的序列号(SYN)。随后,客户回复一个ACK,这样就建立了链接。
现在可以发送和接收消息了。接收消息后,总是返回ACK消息。如果在收到ACK之前发送方已经超时,则消息将被放到重发队列中以再次发送。
由于它的握手机制,所以TCP协议比较复杂并且费时,但此协议在处理数据时对数据包的传送有保障,从而使得在应用程序协议中不需要再包括该功能。
2. Winsock控件
Winsock即Windows Sockets规范的简称,是目前最流行的网络通信应用程序接口之一。所谓Socket,通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过“套接字”向网络发出请求或者应答网络请求。Socket是网络上运行的两个程序间双向通讯的一端,它既可以接受请求,也可以发送请求,利用它可以较为方便的编写网络上数据的传递。Winsock控件工作在传输层上,在这一层上,目前主要流行的协议包括TCP和UDP两种:TCP协议适用于那些对于数据的可靠性要求比较高的情况,目前大多数的网络应用层协议都是基于TCP协议的(例如常用的HTTP、FTP、SMTP、POP3等协议);UDP协议适用于对数据可靠性要求不高而对速度要求较高的情况,这里主要包括一些需要大流量的(例如Real公司的RTSP协议,腾讯公司的QQ协议等)。
2.1.1 Winsock控件重要属性、方法和事件
(1) 属性
Protocol:
通过Protocol属性可以设置WinSock控件连接远程计算机使用的协议。可选的协议是TCP和UDP,对应的VB中常量分别是sckTCPProtocol和sckUDPProtocol,Winsock控件默认协议是TCP。注意:虽然可以在运行时设置协议,但必须在连接未建立或断开连接后。
SocketHandle:
SocketHandle返回当前socket连接的句柄,这是只读属性。
RemoteHostIP:
返回远程计算机的IP地址。在客户端,当使用了控件的Connect方法后,远程计算机的IP地址就赋给了RemoteHostIP属性,而在服务器端,当ConnectRequest事件后,远程计算机(客户端)的IP地址就赋给了这个属性。如果使用的是UDP协议那么当DataArrival事件后,发送UDP报文的计算机的IP才赋给了这个属性。
ByteReceived:
返回当前接收缓冲区中的字节数。
State:
用于返回当前WinSock控件的状态。如表2-1所示。
表1-1 返回WinSock控件当前的状态
(2) 方法
Bind:
用Bind方法可以把一个端口号固定为本控件使用,使得别的应用程序
能再使用这个端口。
Listen:
只在使用TCP协议时有用。它将应用程序置于监听检测状态。
Connect:
当本地计算机希望和远程计算机建立连接时,就可以调用Connect方法。
Accept:
当服务器接收到客户端的连接请求后,服务器有权决定是否接受客户端的
请求。
SendData:
当连接建立后,要发送数据就可以调用SendData方法,该方法只有一个参
数,就是要发送的数据。
GetData:
当本地计算机接收到远程计算机的数据时,数据存放在缓冲区中,要从缓
冲区中取出数据,可以使用GetData方法。
PeekData:
和GetData方法类似,但PeekData在取得数据后并不把缓冲区清空。
(3) 事件
ConnectRequest:
当本地计算机接收到远程计算机发送的连接请求时,控件的ConnectRequest事件将会被触发。
SendProgress:
当一端的计算机正在向另一端的计算机发送数据时,SendProgress事件将
被触发。SendProgress事件记录了当前状态下已发送的字节数和剩余字节数。
SendComplete:
当所有数据发送完成时,被触发。
DataArrival:
当建立连接后,接受到了新数据就会触发这个事件。注意:如果在接受到
新数据前,缓冲区中非空,就不会触发这个事件。
Error:
当在工作中发生任何错误都会触发这个事件。
2.1.2 Winsock控件通信的工作原理 Winsock控件是基于Socket规范创建的,所以其通信的实质是对Socket接口进行数据的读写操作。如果两个应用程序需要通信,它们可以通过使用Socket类来建立套接字连接,可以将这个过程想象为一次电话呼叫过程:呼叫者通过拨号与被呼叫者连接,当电话接通时,双方都可以自由通话了,只不过这里的呼叫者被称为“客户”,被呼叫者则称为“服务器”,而号码则为“IP地址+端口”,但在建立连接之前,必须由“客户”发出呼叫,且此时的“服务器”正在监听。因此,基于TCP/IP协议的通信,需要分别建立客户端应用程序和服务器端应用程序。其大致流程如图1所示:
图1 Winsock工作原理 端口号被规定在0~65535范围内的某一个整数,其中0~1023被预先定义的服务器通信所占用(如telnet占用23,http占用端口80),所以最好使用1024~65535这些端口中的某一个,以免发生端口冲突。
3程序设计与实现
3.1 程序设计
3.1.1总体设计
本程序的文件传输系统的实现应包含服务端模块、客户端模块等几个部分,整个程序采用VB完成。程序使用流式套接字,基于C/S模型。在设计时设计客户端和服务端两个界面中,服务器用于发送文件,客户端用于接收文件。服务器和客户机的基本流程如图2所示。
在通信的时候主要可以分为两个部分,一个部分是控制信息的传输部分,而另一个部分就是文件的传输部分。传送的控制信息可以包含发送文件的请求,文件的名称、大小等,由于这方面的数据量比较小,因此采用了VB所提供的WINSocket类的串行化技术来实现。对于文件的传输,由于数据量相对来说比较大,所以用两个线程来实现文件的传输,一个线程用于发送,一个线程用于接收。
否
是
、
图2 服务器和客户机的基本流程
3.1.2模块设计
(1)服务端模块
客户端要能实现的都功能应该有:能查找要传送的文件;能够侦听连接;能够与客户端建立连接;能共发送数据。客户端要与服务器端进行通信,首先,必须知道服务器端的域名或IP地址(RemoteHost属性),就像要和某人打电话前,必须知道对方的电话号码;其次,还必须和服务器端约定相同的端口(RemotePort属性),用于数据的输入和输出;最后,调用Connect方法与服务器端建立连接。服务器端应设置一个监听端口(LocalPort属性),端口应与客户端的端口相同,同时调用Listen方法时刻监听客户端的连接请求(ConnectionRequest事件);当接收到客户端的连接请求时,可调用ConnectionRequest事件的Accept方法,这样与客户端的连接就建立了。
(2)客户端模块
客户端能实现的功能有:能够与服务器建立连接,能够接受服务器传来的数据;能够保存所接受的数据等。 客户端和服务器端成功建立连接后,任何一方都可以自由的发送数据(SendData方法)和接收数据(GetData方法),这些方法都在DataArrival事件中。
3.2 程序的实现
3.2.1 工作原理
本实验将实现的文件传输只有一个发送方和一个接收方,这是最基本的文件传输方式,运用的原理也比较简单:发送方先获取待传输文件的基本信息,主要是文件名及文件长度(用于创建数据缓冲区);然后,将其发送给接收方;接着,建立和文件一样大小的数据缓冲区,并将文件读入;最后,将数据缓冲区中的数据发送给接收方。与此同时,当接收方接收到文件名和文件长度之后,就为其创建新的文件和数据缓冲区;然后,接收传输的文件数据,并将其放在数据缓冲区中;最后,依次将数据缓冲区的数据写入新创建的文件中。这样便完成了不同计算机之间的文件传输。
然而,当需要传送的数据比较大时,就不能像以上介绍的那样,直接将整个文件放入数据缓冲区中了,我们的内存是无法忍受用一个几百MB甚至上GB的空间去存储那些临时数据的。这时可以将文件按照一定的大小,分成若干个数据包(远小于内存的容量)。首先,设置数据包的大小(如64K),根据文件的基本信息(主要文件的长度),计算出总共需要的数据包数;然后,依次读取同数据包一样大小的数据到数据缓冲区中;接着,将数据缓冲区中的数据,发送到指定的计算机上;同时在另一端,建立一个数据缓冲区,缓冲区的大小要根据接收到的数据来确定,依次接收客户端传输过来的数据包,并将数据缓冲区的数据写入相应的文件中,这样就很容易实现大文件的传输了。 但还有些时候,当我们在传输文件的过程中,突然被意外中断,导致网络连接中断。这时,我们又不得不再次将文件重新传输一次,显然这浪费了不少的时间,那怎样解决这类问题呢?这就涉及到"断点续传"了,即我们可以接着上次未传输完的地方,继续传输文件。 "断点续传"的方法有多种,比较常见的一种是通过设置一个临时文件,记录已经传输的文件信息,当传输文件中断时,可以通过临时文件的数据来推算出未传输的数据;然后,在每次进行文件传输前,都先查找文件是否有临时文件,并将此信息传输给服务器端,于是服务器端可据此再接着进行传输剩余的数据,当文件全部传输完毕时,删除临时文件,这样就实现了"断点续传"。
3.2.2服务器端主程序:
“通用”中声明如下:Option Base 1Const PACKSIZE As Long = 65536 '每包大小为64KDim filepath As String, filename As String, filelength As Long '存储文件信息Dim data() As Byte, pack As Long, send As Long '数据缓冲区,文件包数,已传输的数据“发送文件”按钮事件代码:Private Sub sendfile_Click()StatusBar1.SimpleText = "向客户端发送数据…"'计算需要传输文件的包数pack = (filelength - send) \ PACKSIZEIf ((filelength - send) Mod PACKSIZE) <> 0 Then pack = pack + 1If pack = 0 Then pack = pack + 1'传输文件Open filepath For Binary As #1For i = 1 To pack'如果只有一包If pack = 1 ThenReDim data(filelength - send)'读取数据For j = send + 1 To filelengthGet #1, j, data(j - send)Next'更新已传输文件的数据send = filelength'发送文件数据Winsock1.SendData data'如果是最后一包ElseIf i + 1 = pack Then'读取最后一包的数据ReDim data(filelength - send)For j = 1 To filelength - sendGet #1, send + j, data(j)Next'发送文件数据Winsock1.SendData data'更新已传输文件的数据send = filelengthExit ForElse'将文件数据放到数据缓冲区ReDim data(PACKSIZE)For j = 1 To PACKSIZEGet #1, send + j, data(j)Next'发送文件数据Winsock1.SendData data'更新已传输文件的数据send = send + PACKSIZEEnd IfProgressBar1.Value = Int((send / filelength) * 100)NextProgressBar1.Value = Int((send / filelength) * 100)Close #1End Sub'返回客户端已接收文件的数据Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)Winsock1.GetData send, vbLongEnd Sub
"开启"按钮事件的代码:Private Sub start_Click()Winsock1.Protocol = sckTCPProtocol '以TCP方式进行通信'设置服务器通信程序的端口号,这里笔者使用的端口是8080Winsock1.LocalPort = Val(portText.Text)Winsock1.Listen '等待客户端连接请求'状态栏显示提示文字StatusBar1.SimpleText = "服务器已工作,准备接受请求…"End Sub"客户端请求连接"事件代码:Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)'如果当前连接是打开的,则关闭If Winsock1.State <> 0 ThenWinsock1.CloseEnd IfWinsock1.Accept requestID '接受客户请求StatusBar1.SimpleText = "有客户请求,建立连接。"End SubPrivate Sub Dir1_Change()
File1.Pattern = ("*.*")
File1.Path = Dir1.Path
End Sub
Private Sub Drive1_Change()
Dir1.Path = Drive1.Drive
End Sub
Private Sub file1_Click()
Label2.Caption = "你选择的是: " & Dir1.List(-1) & "\" & File1.filename
filepath = File1.filename
filelength = FileLen(Dir1.List(-1) & "\" & File1.filename)
End Sub 运行效果如图3所示:
图3 服务器端断点续传的运行效果
3.2.3客户端主程序
Option Base 1Dim flag As Boolean '设置开关Dim filename As String, filelength As Long '存储文件信息Dim data() As Byte, received As Long '声明数据缓冲区和已接收的数据'初始化开关Private Sub Form_Load()flag = TrueEnd Sub"连接"按钮事件的代码:Private Sub connect_Click()Winsock1.Protocol = sckTCPProtocol '以TCP方式进行通信'设置远程服务器IP地址,为方便调试笔者使用的是自身的IP地址Winsock1.RemoteHost = hostText.Text'设置远程服务器通信程序端口号,与服务器端相同Winsock1.RemotePort = Val(portText.Text)Winsock1.connect '与服务器端建立连接End Sub"数据到达"事件的代码:Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)StatusBar1.SimpleText = "正在接收服务器的数据..."If flag = True Then'分别接收传输文件的文件名、文件长度Winsock1.GetData filename, vbString, bytesTotal - 4Winsock1.GetData filelength, vbLong'为传输文件设置临时文件tempfile = filename + ".td"'返回已接收的数据Open “d:\”+ filename For Binary As #1Open tempfile For Binary As #2If LOF(2) > 0 ThenInput #2, receivedWinsock1.SendData receivedEnd IfClose #2flag = FalseElseOpen tempfile For Output As #2'建立数据缓冲区ReDim data(bytesTotal)'接收服务器端传输的数据Winsock1.GetData data, vb + vbByte'将接收的数据写入文件For j = received + 1 To received + bytesTotalPut #1, j, data(j - received - 1)Next'更新已接收的数据received = received + bytesTotal'更新临时文件Write #2, receivedProgressBar1.Value = Int((received / filelength) * 100)'传输完毕If ProgressBar1.Value >= 100 ThenStatusBar1.SimpleText = "数据传输完毕!"Close #2'删除临时文件Kill (tempfile)Close #1End IfClose #2End IfEnd Sub运行效果如图4所示:
图4 客户端断点续传的效果
4、总结
整个设计到目前为止已基本完成,从选择这个设计课题开始,对winsock控件一无所知到现在能够独立完成本次设计,从中获益非浅。在设计中碰到了很多所未预料的棘手的难题,通过图书馆查阅资料,上网搜索相关知识以及通过VBQQ群里的朋友的帮助,逐个逐个的解决难题。同时,对自己程序设计的思维和问题解决能力也是一个很大的提高。
本课题设计了基于VB的网络数据传输的C/S模型以及控制端和受控端模型。其中Winsock控件、文件夹的传输、添加客户端,是设计的重点和难点。每个模块都通过了多次的实验和测试。
本文通过在VB中使用Winsock控件,实现网络之间的文件传输,更进一步理解了其工作原理。此外,还研究在网络传输文件中要注意的问题,并对怎样处理传输文件比较大时的情况进行了详细的分析,并通过实际的方法实现了文件的“断点续传”,可以满足实际中的要求,其设计的思想也具有普遍的通用性。
通过此次的毕业设计,从另一个角度加深了自己的编程和软件开发的能力。首先,对设计的需求和功能设计要有全局的了解和掌握。在初次拿到这个课题时对winsock控件作了一番了解,简单实现了字符的通信;在此基础上设计本课题需要实现的功能模块。在实际编程过程中,对于客户端的断开再连接实现操作一直是个难题,同时深层次的文件夹传输也困扰了许久。。
在本次设计中所遇到的一些难点,都是由自己寻求各种途径和方案最终将其解决,在编程和设计思路上有了新的提升。
[1] 崔彦锋,许小荣.VB网络与远程控制编程实例教程[M].北京:北京希望电子出版社,1996.34~65
[2] 卞志强.Visual Basic网络程序设计[M].北京:人民邮电出版社,1993.48~93
[3] 肖斌,董磊.Visual Basic 6 网络编程实例教程[M]北京:北京希望电子出版社, 1998.47~139
[4] Loren Eidahl.Visual Basic控件设计与开发[M].浙江:浙江科学技术出版社,1998.26~89
[5]魏江江.Visual Basic API编程百例通[M].北京:科学出版社,2001.45~78
[6]高春艳,刘彬彬. Visual Basic空件大全[M].北京:人民邮电出版社,1991.15~31
¥29.8
¥9.9
¥59.8