基于UDP的文件传输

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

报告编号:11 综合课程设计报告
基于UDP协议的文件传输系统的设计与实现
学生姓名:
指导教师:
所在系:电子系
所学专业:电子信息工程
年级:08级电子(2)班
2011 年6 月
目录
摘要 (3)
1 实验的相关知识 (4)
1.1通信的模式 (4)
1.2 UDP协议 (4)
1.3 Winsock控件 (4)
1.3.1 Winsock控件重要属性、方法和事件 (5)
1.3.2 Winsock控件通信的工作原理 (7)
2 实验原理 (7)
3 实验步骤 (7)
3.1总体规划 (8)
3.2模块设计 (8)
3.3创建窗体 (8)
3.4程序设计 (10)
3.5系统运行 (11)
4实验结论 (12)
参考文献 (13)
基于UDP的文件传输的系统的设计与实现
摘要
该实验的任务是实现文件的传输,并且是基于UDP协议的。

所有文件在该协议下可以实现发送并正确接收。

此时需要了解的是UDP的数据包一次最多只能发送8K,所以我们想到通过拆包和创建窗体的方法来实现文件的传输。

拆包主要是规定每个数据包的大小,然后计算具体的文件所需要的包数,创建窗体的目的是编写程序来进行分包发送和接收。

通过系统运行窗体我们可以知道UDP不仅可以传送和接收小文件,还可以传输和接收较大的文件。

通过实验可知UDP是不可靠的无连接传输,所以在传输过程中会发生丢包的情况,但大部分情况下传输还是比较好的。

关键词:UDP协议发送文件接收文件拆包 Winsock控件
1 实验的相关知识
1.1通信的模式
由于是实现点对点的文件传输,因此在程序中我们使用的是C/S的模式来实现通信。

对于C/S的模式,即分为客户端和服务端。

服务端用来接收客户端的连接,实现两端之间互相传输文件。

采用C/S的模式可以更好的体现程序的功能设计思想,充分调用在LAN中的server和client两方面的处理能力,极大的减少网络上的信息流通量。

C/S体系结构有可能提供一种开放式的、易伸缩扩展的分布式计算机环境,并保护硬件等投资。

1.2 UDP协议
该实验文件传输是在UDP协议下进行的,UDP提供无连接不可靠的用户数据包传输。

其中每一个数据段只有8Byte相对于TCP传输开销较少,且无须对发送速率进行管理。

UDP发送数据的速率仅仅受限于程序产生数据的速率,信源主机的性能及internet上可以利用的宽带。

并且与TCP不同的是UDP不需要连接,可直接发送,传输数据较快,但同时其稳定性不好,易丢包。

1.3 Winsock控件
Winsock即Windows Sockets规范的简称,是目前最流行的网络通信应用程序接口之一。

所谓Socket,通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。

应用程序通常通过“套接字”向网络发出请求或者应答网络请求。

Socket是网络上运行的两个程序间双向通讯的一端,它既可以接受请求,也可以发送请求,利用它可以较为方便的编写网络上数据的传递。

Winsock控件工作在传输层上,在这一层上,目前主要流行的协议包括TCP和UDP两种:TCP协议适用于那些对于数据的可靠性要求比较高的情况,目前大多数的网络应用层协议都是基于TCP协议的(例如常用的HTTP、FTP、SMTP、POP3等协议);UDP 协议适用于对数据可靠性要求不高而对速度要求较高的情况,这里主要包括一些需要大流量
的(例如Real公司的RTSP协议,腾讯公司的QQ协议等)。

1.3.1 Winsock控件重要属性、方法和事件
(1) 属性
Protocol:
通过Protocol属性可以设置WinSock控件连接远程计算机使用的协议。

可选的协议是TCP和UDP,对应的VB中常量分别是sckTCPProtocol和sckUDPProtocol,Winsock控件默认协议是UDP。

RemoteHostIP:
返回远程计算机的IP地址。

本实验使用的是UDP协议,那么当DataArrival事件后,发送UDP报文的计算机的IP才赋给了这个属性。

如果是TCP协议,在客户端,当使用了控件的Connect方法后,远程计算机的IP地址就赋给了RemoteHostIP属性,而在服务器端,当ConnectRequest事件后,远程计算机(客户端)的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:(TCP)
当本地计算机接收到远程计算机发送的连接请求时,控件的ConnectRequest事件将会被触发。

SendProgress:
当一端的计算机正在向另一端的计算机发送数据时,SendProgress事件将
被触发。

SendProgress事件记录了当前状态下已发送的字节数和剩余字节数。

SendComplete:
当所有数据发送完成时,被触发。

DataArrival:
当建立连接后,接受到了新数据就会触发这个事件。

注意:如果在接受到
新数据前,缓冲区中非空,就不会触发这个事件。

Error:
当在工作中发生任何错误都会触发这个事件。

1.3.2 Winsock控件通信的工作原理
Winsock控件是基于Socket规范创建的,所以其通信的实质是对Socket接口进行数据的读写操作。

如果两个应用程序需要通信,它们可以通过使用Socket类来建立套接字连接,可以将这个过程想象为一次电话呼叫过程:呼叫者通过拨号与被呼叫者连接,当电话接通时,双方都可以自由通话了,只不过这里的呼叫者被称为“客户”,被呼叫者则称为“服务器”,而号码则为“IP地址+端口”,但在建立连接之前,必须由“客户”发出呼叫,且此时的“服务器”正在监听。

注意端口号被规定在0~65535范围内的某一个整数,其中0~1023被预先定义的服务器通信所占用(如telnet占用23,http占用端口80),所以最好使用1024~65535这些端口中的某一个,以免发生端口冲突。

2 实验原理
实验设计过程中主要是通过Winsock控件进行UDP文件传输。

分别在发送端和接收端建立控件Winsock,经过对Winsock控件程序的写入,然后通过端口号和IP地址的绑定来建立联系,而无需像TCP一样建立连接,直接可以传送文件,而且能较准确的发送和接收。

下图是UDP数据报的封装:
3 实验步骤
3.1总体规划
根据该实验的要求在UDP协议下实现文件的传输。

本程序的文件传输系统的实现应包含服务端模块、客户端模块等几个部分,整个程序采用VB完成。

程序使用流式套接字,基于C/S模型。

在设计时设计客户端和服务端两个界面中,服务器用于发送文件,客户端用于接收文件。

服务器和客户机的基本流程如图2所示。

在通信的时候主要可以分为两个部分,一个部分是控制信息的传输部分,而另一个部分就是文件的传输部分。

传送的控制信息可以包含发送文件的请求,文件的名称、大小等,由于这方面的数据量比较小,因此采用了VB所提供的WINSocket类的串行化技术来实现。

对于文件的传输,由于数据量相对来说比较大,所以用两个线程来实现文件的传输,一个线程用于发送,一个线程用于接收。

3.2模块设计
(1)服务端模块
服务端要与客户端进行通信,首先,必须知道客户端的域名或IP地址(RemoteHost 属性),就像要和某人打电话前,必须知道对方的电话号码;其次,还必须和客户端进行端口绑定,也就是端口号要匹配,这样传送的文件才能到达客户端。

而且每个文件都有自己文件的长度和大小等。

且能传送任意磁盘中任意文件夹中的文件。

(2)客户端模块
同样地,客户端也需要有服务端的端口号和IP地址,而且还能把接收到的文件放到自己想要的磁盘中。

3.3创建窗体
发送和接收窗口能要有远程IP端口地址、发送端口号、接收端口号、发送和接收文件所处位置、发送按键、Winsock等,发送端窗体如图(1)和接收端口窗体如图(2)。

图1
图2
3.4程序设计
在窗口建好的情况下相应的编写程序,在程序中关键是发送和接收,而数据传输过程关键方法是拆包,用VB可以写出拆包发送和接收程序段。

1)发送端发送程序段如下:
Private Sub sendfile_Click()
StatusBar1.SimpleText = "向客户端发送数据…" '计算需要传输文件的包数
pack = (filelength - send) \ PACKSIZE
If ((filelength - send) Mod PACKSIZE) <> 0 Then pack = pack + 1
If pack = 0 Then pack = pack + 1 '传输文件
Open filepath For Binary As #1
For i = 1 To pack '如果只有一包
If pack = 1 Then
ReDim data(filelength - send) '读取数据
For j = send + 1 To filelength
Get #1, j, data(j - send)
Next '更新已传输文件的数据
send = filelength '发送文件数据
Winsock1.SendData data '如果是最后一包ElseIf i = pack Then '读取最后一包的数据
ReDim data(filelength - send)
For j = 1 To filelength - send
Get #1, send + j, data(j)
Next '发送文件数据
Winsock1.SendData data '更新已传输文件的数据
send = filelength
Exit For
Else '将文件数据放到数据缓冲区ReDim data(PACKSIZE)
For j = 1 To PACKSIZE
Get #1, send + j, data(j)
Next '发送文件数据
Winsock1.SendData data '更新已传输文件的数据
send = send + PACKSIZE
End If
ProgressBar1.Value = Int((send / filelength) * 100)
Next
ProgressBar1.Value = Int((send / filelength) * 100)
If ProgressBar1.Value >= 100 Then
StatusBar1.Panels(1).Text = "数据传输完毕!"
Close #1
End If
End Sub
2)接收端接收程序如下:
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
StatusBar1.SimpleText = "正在接收服务器的数据..."
If flag = True Then
'分别接收传输文件的文件名、文件长度
Winsock1.GetData FileName, vbString, bytesTotal - 4
Winsock1.GetData filelength, vbLong
'为传输文件设置临时文件
tempfile = FileName + ".td"
'返回已接收的数据
Open Dir1 + FileName For Binary As #1
Open tempfile For Binary As #2
If LOF(2) > 0 Then
Input #2, received
Winsock1.SendData received
End If
Close #2
flag = False
Else
Open tempfile For Output As #2
ReDim data(bytesTotal) '建立数据缓冲区
Winsock1.GetData data, vbArray + vbByte '接收服务器端传输的数据
For j = received + 1 To received + bytesTotal '将接收的数据写入文件
Put #1, j, data(j - received - 1)
Next
received = received + bytesTotal 更新已接收的数据
Write #2, received '更新临时文件
ProgressBar1.Value = Int((received / filelength) * 100) '传输完毕
If ProgressBar1.Value >= 100 Then
StatusBar1.SimpleText = "数据传输完毕!"
3.5系统运行
不断将程序完善直到可以进行运行,系统运行结果如图(3)(4)。

图(3)是数据发送完毕情况图(4)是数据接收完毕情况
图3
图4
4实验结论
刚开始拿到题目时根本无从下手,后来通过老师的讲解,知道我们这个实验可以通过
Winsock控件来实现,大致了解了整个框架。

但我们对控件的运用不是很清楚,于是去图书馆查阅相关资料、上网搜索相关知识,对Winsock控件有了一个基本的了解。

于是慢慢去构思,一步一步去实现基于UDP的文件传输,并基本成功了。

实验中我们了解到UDP传输文件的大小是有界限的,而这一问题可以通过数据拆包的方法来解决。

通过这一实验,我们了解到团队精神的重要性,同时强化了自己的动手能力和编程能力。

对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
附录A 发送窗口
Option Base 0
Const PACKSIZE As Long = 8191
Dim filepath As String, filename As String, filelength As Long '存储文件信息
Dim data() As Byte, pack As Long, send As Long '数据缓冲区,文件包数,已传输的数据
Private Sub Command1_Click()
End
End Sub
Private Sub Dir1_Change()
File1.Path = Dir1.Path
Label6.Caption = Dir1.Path
Label5.Caption = File1.List(0)
End Sub
Private Sub Drive1_Change()
Dir1.Path = Drive1.Drive
File1.Path = Dir1.Path
Label6.Caption = File1.List(0)
Label5.Caption = File1.List(0)
End Sub
Private Sub File1_Click()
Dim i As Integer
Dim RemoteIP As String, RemotePort As Long
RemoteIP = Me.Text2.Text
RemotePort = Val(Me.Text3.Text)
Me.Winsock1.RemoteHost = RemoteIP
Me.Winsock1.RemotePort = RemotePort
i = File1.ListIndex
Label5.Caption = File1.List(i)
filename = File1.filename
filepath = File1.Path + "\" + File1.filename
filelength = FileLen(filepath)
Winsock1.SendData filename
Winsock1.SendData filelength
End Sub
Private Sub Form_Load()
Dim LocalPort As Long
LocalPort = Val(Me.Text1.Text)
Me.Winsock1.Protocol = sckUDPProtocol
Me.Winsock1.Bind LocalPort
End Sub
Private Sub sendfile_Click()
StatusBar1.SimpleText = "向客户端发送数据…" '计算需要传输文件的包数
pack = (filelength - send) \ PACKSIZE
If ((filelength - send) Mod PACKSIZE) <> 0 Then pack = pack + 1
If pack = 0 Then pack = pack + 1 '传输文件
Open filepath For Binary As #1
For i = 1 To pack '如果只有一包
If pack = 1 Then
ReDim data(filelength - send) '读取数据
For j = send + 1 To filelength
Get #1, j, data(j - send)
Next '更新已传输文件的数据
send = filelength '发送文件数据
Winsock1.SendData data '如果是最后一包ElseIf i = pack Then '读取最后一包的数据
ReDim data(filelength - send)
For j = 1 To filelength - send
Get #1, send + j, data(j)
Next '发送文件数据
Winsock1.SendData data '更新已传输文件的数据
send = filelength
Exit For
Else '将文件数据放到数据缓冲区ReDim data(PACKSIZE)
For j = 1 To PACKSIZE
Get #1, send + j, data(j)
Next '发送文件数据
Winsock1.SendData data '更新已传输文件的数据
send = send + PACKSIZE
End If
ProgressBar1.Value = Int((send / filelength) * 100)
Next
ProgressBar1.Value = Int((send / filelength) * 100)
If ProgressBar1.Value >= 100 Then
StatusBar1.Panels(1).Text = "数据传输完毕!"
Close #1
End If
End Sub
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Winsock1.GetData send, vbLong '返回客户端已接收文件的数据End Sub
附录A 接收窗口代码
Option Base 0
Dim flag As Boolean
Dim FileName As String, filepath As String, filelength As Long
Dim data() As Byte, received As Long
Dim tempfile As String
Private Sub Command1_Click()
Dim RemoteIP As String, RemotePort As Long
RemoteIP = Me.Text1.Text
RemotePort = Val(Me.Text3.Text)
Me.Winsock1.RemoteHost = RemoteIP
End
End Sub
Private Sub Dir1_Change()
File1.Path = Dir1.Path
Label7.Caption = Dir1.Path
Label9.Caption = File1.List(0)
End Sub
Private Sub Drive1_Change()
Dir1.Path = Drive1.Drive
File1.Path = Dir1.Path
Label7.Caption = File1.List(0)
Label9.Caption = File1.List(0)
End Sub
Private Sub File1_Click()
Dim i As Integer
Dim RemoteIP As String, RemotePort As Long
RemoteIP = Me.Text1.Text
RemotePort = Val(Me.Text3.Text)
Me.Winsock1.RemoteHost = RemoteIP
Me.Winsock1.RemotePort = RemotePort
i = File1.ListIndex
Label9.Caption = File1.List(i)
FileName = File1.FileName
filepath = File1.Path + "\" + File1.FileName
filelength = FileLen(filepath)
Winsock1.SendData FileName
Winsock1.SendData filelength
End Sub
Private Sub Form_Load()
flag = True
Dim LocalPort As Long
LocalPort = Val(Me.Text2.Text)
Me.Winsock1.Protocol = sckUDPProtocol
Me.Winsock1.Bind LocalPort
End Sub
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
StatusBar1.SimpleText = "正在接收服务器的数据..."
If flag = True Then
'分别接收传输文件的文件名、文件长度
Winsock1.GetData FileName, vbString, bytesTotal - 4 Winsock1.GetData filelength, vbLong
'为传输文件设置临时文件
tempfile = FileName + ".td"
'返回已接收的数据
Open Dir1 + FileName For Binary As #1
Open tempfile For Binary As #2
If LOF(2) > 0 Then
Input #2, received
Winsock1.SendData received
End If
Close #2
flag = False
Else
Open tempfile For Output As #2
'建立数据缓冲区
ReDim data(bytesTotal)
'接收服务器端传输的数据
Winsock1.GetData data, vbArray + vbByte
'将接收的数据写入文件
For j = received + 1 To received + bytesTotal
Put #1, j, data(j - received - 1)
Next
'更新已接收的数据
received = received + bytesTotal
'更新临时文件
Write #2, received
ProgressBar1.Value = Int((received / filelength) * 100) '传输完毕
If ProgressBar1.Value >= 100 Then
StatusBar1.SimpleText = "数据传输完毕!"
Close #2
'删除临时文件
Kill (tempfile)
Close #1
End If
Close #2
End If
End Sub
(附录2:成评定单绩记载页格式,本括号内信息不打印)
安徽师范大学皖江学院
课程设计成绩评定单。

相关文档
最新文档