Listen(),监听来自客户端的连接 是否有连接否 接收客户端的连接请求 是 显示错误 是否有建不为客户端建立连接,显示错误信息 、 在套接字上收发信息 否 为客户端建立连接 ,在套接字上收发信息 图2 服务器和客户机的基本流程 3.1.2模块设计 (1)服务端模块 客户端要能实现的都功能应该有:能查找要传送的文件;能够侦听连接;能够与客户端建立连接;能共发送数据。客户端要与服务器端进行通信,首先,必须知道服务器端的域名或IP地址(RemoteHost属性),就像要和某人打电话前,必须知道对方的电话号码;其次,还必须和服务器端约定相同的端口(RemotePort属性),用于数据的输入和输出;最后,调用Connect方法与服务器端建立连接。服务器端应设置一个监听端口(LocalPort属性),端口应与客户端的端口相同,同时调用Listen方法时刻监听客户端的连接请求(ConnectionRequest事件);当接收到客户端的连接请求时,可调用ConnectionRequest事件的Accept方法,这样与客户端的连接就建立了。
(2)客户端模块
客户端能实现的功能有:能够与服务器建立连接,能够接受服务器传来的数据;能够保存所接受的数据等。 客户端和服务器端成功建立连接后,任何一方都可以自由的发送数据(SendData方法)和接收数据(GetData方法),这些方法都在DataArrival事件中。
程序的实现 3.2.1 工作原理
本实验将实现的文件传输只有一个发送方和一个接收方,这是最基本的文件传输方式,运用的原理也比较简单:发送方先获取待传输文件的基本信息,主要是文件名及文件长度(用于创建数据缓冲区);然后,将其发送给接收方;接着,建立和文件一样大小的数据缓冲区,并将文件读入;最后,将数据缓冲区中的数据发送给接收方。与此同时,当接收方接收到文件名和文件长度之后,就为其创建新的文件和数据缓冲区;然后,接收传输的文件数据,并将其放在数据缓冲区中;最后,依次将数据缓冲区的数据写入新创建的文件中。这样便完成了不同计算机之间的文件传输。
然而,当需要传送的数据比较大时,就不能像以上介绍的那样,直接将整个文件放入数据缓冲区中了,我们的内存是无法忍受用一个几百MB甚至上GB的空间去存储那些临时数据的。这时可以将文件按照一定的大小,分成若干个数据包(远小于内存的容量)。首先,设置数据包的大小(如64K),根据文件的基本信息(主要文件的长度),计算出总共需要的数据包数;然后,依次读取同数据包一样大小的数据到数据缓冲区中;接着,将数据缓冲区中的数据,发送到指定的计算机上;同时在另一端,建立一个数据缓冲区,缓冲区的大小要根据接收到的数据来确定,依次接收客户端传输过来的数据包,并将数据缓冲区的数据写入相应的文件中,这样就很容易实现大文件的传输了。
但还有些时候,当我们在传输文件的过程中,突然被意外中断,导致网络连接中断。这时,
我们又不得不再次将文件重新传输一次,显然这浪费了不少的时间,那怎样解决这类问题呢这就涉及到"断点续传"了,即我们可以接着上次未传输完的地方,继续传输文件。
"断点续传"的方法有多种,比较常见的一种是通过设置一个临时文件,记录已经传输的文件信息,当传输文件中断时,可以通过临时文件的数据来推算出未传输的数据;然后,在每次进行文件传输前,都先查找文件是否有临时文件,并将此信息传输给服务器端,于是服务器端可据此再接着进行传输剩余的数据,当文件全部传输完毕时,删除临时文件,这样就实现了"断点续传"。
3.2.2服务器端主程序:
“通用”中声明如下: Option Base 1
Const PACKSIZE As Long = 65536 '每包大小为64K
Dim filepath As String, filename As String, filelength As Long '存储文件信息
Dim data() As Byte, pack As Long, send As Long '数据缓冲区,文件包数,已传输的数据 “发送文件”按钮事件代码: Private Sub sendfile_Click() = \向客户端发送数据…\ '计算需要传输文件的包数 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 '发送文件数据 data
'如果是最后一包 ElseIf i + 1 = pack Then '读取最后一包的数据 ReDim data(filelength - send) For j = 1 To filelength - send Get #1, send + j, data(j) Next
'发送文件数据 data
'更新已传输文件的数据 send = filelength Exit For Else
'将文件数据放到数据缓冲区 ReDim data(PACKSIZE) For j = 1 To PACKSIZE Get #1, send + j, data(j)
Next
'发送文件数据 data
'更新已传输文件的数据 send = send + PACKSIZE End If
= Int((send / filelength) * 100) Next
= Int((send / filelength) * 100) Close #1 End Sub
'返回客户端已接收文件的数据
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long) send, vbLong End Sub
\开启\按钮事件的代码: Private Sub start_Click()
= sckTCPProtocol '以TCP方式进行通信
'设置服务器通信程序的端口号,这里笔者使用的端口是8080 = Val
'等待客户端连接请求 '状态栏显示提示文字
= \服务器已工作,准备接受请求…\ End Sub
\客户端请求连接\事件代码:
Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)
(完整word版)基于TCP的文件传输实验报告



