VBSOCKET实现文件传输
- 格式:docx
- 大小:17.31 KB
- 文档页数:11
先查看MSDN帮助系统,找到socket类,有详细的创建套接字、使用套接字侦听、使用客户端套接字的说明。
打开 2003,新建一个工程,名称为Server。
在界面上添加一个列表框,两个按钮。
界面如图所示:我们使用多线程来实现先导入命名空间:Imports .socketsImports Imports System.TextImports System.Threading定义两个窗体变量Dim s As Socket = NothingDim t As Thread新建一个过程,用于处理接收到的Socket数据包Public Sub WaitData()s = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)'''使用TCP协议Dim localEndPoint As New IPEndPoint(IPAddress.Parse("127.0.0.1"), 1024) '''指定IP和Ports.Bind(localEndPoint) '''绑定到该Sockets.Listen(100) '''侦听,考试#大提示最多接受100个连接While (True)Dim bytes(1024) As Byte '''用来存储接收到的字节Dim ss As Socket = s.Accept() '''若接收到,则创建一个新的Socket与之连接ss.Receive(bytes) '''接收数据,若用ss.send(Byte()),则发送数据ListBox1.Items.Insert(0, Encoding.Unicode.GetString(bytes))'''将其插入到列表框的第一项之前'''若使用Encoding.ASCII.GetString(bytes),则接收到的中文字符不能正常显示End WhileEnd Sub在BtnStart的click事件中,加入如下代码:t = New Thread(AddressOf WaitData) '''建立新的线程t.Start() '''启动线程BtnStart.Enabled = False '''按钮不可用,避免另启线程在BtnStop的click事件中,加入如下代码:Trys.Close() '''关闭Sockett.Abort() '''中止线程CatchFinallyBtnStart.Enabled = True '''启用BtnStartEnd Try为了防止用户不点击Stop直接退出,而不能使线程结束,则应在窗体的closing事件中,加入如下代码:Trys.Close()t.Abort()CatchEnd Try下面新建一个工程,名称为Client。
socket传输文件的原理
文件传输是计算机网络中的一项基本功能,它允许在网络上的不同计算机之间共享和传输文件。
Socket是实现文件传输的一种常用方式,其原理如下:
1. 建立连接:在进行文件传输之前,需要在发送方和接收方之间建立连接。
这通常通过TCP/IP 协议实现,使用Socket进行连接的建立。
一旦连接建立成功,发送方和接收方就可以通过该连接进行数据传输。
2. 文件分割:由于文件通常较大,不适合一次性传输,因此需要将文件分割成较小的数据块。
这些数据块可以按照一定的顺序进行编号,以便于接收方重新组合成完整的文件。
3. 发送数据:发送方通过Socket将分割好的数据块逐个发送给接收方。
在发送数据时,需要按照一定的协议进行数据的封装,例如添加文件名、数据块大小等信息。
4. 接收数据:接收方通过Socket接收到数据后,需要按照发送方的协议对数据进行解析和处理。
接收方会将收到的数据块进行缓存,以便后续重新组合成完整的文件。
5. 确认机制:为了确保文件传输的完整性和正确性,发送方和接收方之间需要建立一种确认机制。
例如,发送方可以发送一个数据包的编号给接收方,接收方在收到数据包后回复一个确认信号给发送方,表示该数据包已经成功接收。
如果发送方在一定时间内没有收到确认信号,则会重新发送数据包,以确保数据的可靠传输。
6. 关闭连接:当文件传输完成后,发送方和接收方之间的连接会被关闭。
这可以通过Socket 的关闭函数实现,释放网络资源。
通过以上步骤,使用Socket可以实现文件的传输。
在实际应用中,不同的文件传输协议可能会有一些差异,但基本原理是相同的。
使⽤socket进⾏服务端与客户端传⽂件的⽅法逻辑:1.客户端将需要查找的⽂件名以流的形式传给服务端2.服务端接受客户端的连接,把流转化为字符串,进⾏⼀个⽬录的遍历,查找是否存在需要的⽂件,若未找到,则输出未找到,若找到,则将⽂件转化为流,传给客户端3.客户端准备接受,将服务端传过来的流转化为⽂件,存储下载。
4,⾄此,完成⼀个简单的客户端与服务端传输⽂件的⼩栗⼦~Client.Javapackage com.ysk;import java.io.BufferedReader;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.io.PrintWriter;import .ServerSocket;import .Socket;import .UnknownHostException;public class Client {public static void main(String[] args) {try {Socket socket = new Socket("127.0.0.1", 5555);OutputStream os = socket.getOutputStream();// 字节输出流PrintWriter pw = new PrintWriter(os);pw.write("aa.txt");//输⼊需要搜索的⽂件名pw.flush();socket.shutdownOutput();BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));String a = "";String temp = "";while ((temp = in.readLine()) != null) {a += temp;}PrintWriter out = new PrintWriter(new OutputStreamWriter(new FileOutputStream("src\\asb.txt")));out.write(a);out.flush();out.close();} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {}}}Server.javapackage com.ysk;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import .ServerSocket;import .Socket;public class Server {static ServerSocket serverSocket;public static void main(String[] args) {try {serverSocket = new ServerSocket(5555);System.out.println("***服务器即将启动,等待客户端的连接***");Socket socket = serverSocket.accept();BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));String file = br.readLine();findFile("src", file);if (result) {System.out.println("已找到" + file);File f = new File(file);// File copyfile = new File("src\\file", "bb.txt");BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(filepath + file)));System.out.println(filepath + file);String a = "";String temp = "";while ((temp = in.readLine()) != null) {a += temp;}PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));out.write(a);out.flush();socket.shutdownOutput();} else {System.out.println("未找到⽂件");}} catch (IOException e) {e.printStackTrace();}}需⾃备aa.txt,这种资源⽂件,以便测试。
VB中使用WinSock控件传送文件传送文件对于网络编程来说是基本的功能,比如远程控制软件。
在编制一个软件时,我从网上下了很多传文件的程序,这些程序提供的传文件功能根本就不能用。
传文本还可以,传二进制文件根本就不行。
因此,作为一个基本的功能模块,有必要单独介绍一下。
首先,在VB中要传送字符串,你可以这样写:DimstrDataAsStringstrData="Test"但是如果你传送的二进制文件,你还能用String变量来存放吗?从理论上分析是不行的,我也做了实验,确实是不行的。
文件虽然可以传,但是接受的文件和发送的不一样,原因可能是二进制文件里可以有任何"字符",但是不是所有的字符都可以放在String变量里。
除了String类型的变量,VB中其他类型的变量都只有几个字节长,难道一次只能发几个字节吗?那样岂不是要累死机器了!其实,情况没有那么悲观,我们完全可以使用数组来解决这个问题,就是使用byte数组。
把要传送的文件都读到数组里,然后发送出去。
程序如下:FileName为要传送的文件名,WinS为发送文件的WinSock控件。
这是一个发送端的程序。
PublicSubSendFile(FileNameAsString,WinSAsWinsock)DimFreeFAsInteger'空闲的文件号DimLenFileAsLong'文件的长度DimbytData()AsByte'存放数据的数组FreeF=FreeFile'获得空闲的文件号OpenFileNameForBinaryAs#FreeFile'打开文件DoEventsLenFile=LOF(FreeF)'获得文件长度ReDimbytData(1ToLenFile)'根据文件长度重新定义数组大小Get#FreeF,,bytData'把文件读入到数组里Close#FreeF'关闭文件'发送数据EndSub接受端的程序如下:PrivateSubWinsock1_DataArrival(ByValbytesTotalAsLong) DimbytData()AsByteDimff=FreeFileOpenstrFileNameForBinaryAs#fReDimbytData(1TobytesTotal)Put#f,i,bytDatai=i+bytesTotal'保证每次写都是在文件的末尾,i是个全局变量Close#fEndSub这里有两个需要注意的地方,ReDimPreservebytData(1ToLenFile),下标是从1开始的,如果你写成ReDimbytData(LenFile),下标就是从0开始了,数组就有LenFile+1长了。
基于VB编程实现网络文件数据传递的实现作者:叶纪听来源:《电脑知识与技术》2014年第22期摘要:跟着Internet的遍及和工业自动化的迅速发展,网络已深化家庭、单位、工厂、自动化操控领域。
大家在各个地方都可经过互联网来交流信息,因而网络数据传输就显得尤为的重要。
在VB中就供给了撑持数据传输的控件,如:Winsock控件和MSComm控件等。
经过程序开发和控件的运用,可完成网络的数据通信,满意网络用户对数据通信和数据交流的需要。
关键词:vb编程;文件;网络数据;传递中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2014)22-5235-051 VB网络文件数据传输及通信概述1.1 数据通讯方法按传输方向分有:1)单工通讯:在单工信道上信息只能在一个方向传送。
2)半双工通讯:在半双工信道上,通讯的双方可替换发送和接纳信息。
3)全双工通讯:一种能够一起进行双向信息传送的通讯方法。
1.2交流方法1)线路交流:交流的特色是树立衔接需求等候较长的时刻。
特色:衔接树立后通路是专用的。
不再有传输推迟,这种交流方法适合于传输大量的数据。
在传输少量信息时功率不高。
2)报文交流:特色:不树立专用链路。
线路利用率较高。
电子邮件系统(例如E-Mail)适合选用报文交流方法。
虚电路能够是暂时的,即会话开端树立,会话完毕撤除,这叫虚呼叫;也能够是持久的,即通讯双方一开机就自动树立,直到一方(或一起)关机才撤除。
这叫持久虚电路。
分组交流的特色:数据包有固定的长度。
选用固定的、短的分组相对于报文交流是一个重要的长处。
除了交流结点的存储缓冲区能够不些外,也带来了传播时延的削减,分组交流也意味着按分组纠错:发现过错只需重发犯错的分组,使通讯功率提高。
2 VB网络文件数据传递性能需求2.1 稳定性在程序规划中应当考虑到各种可能发作的状况,进而避免惯例或许一些低级过错。
一旦发作任何过错或突发事件,体系要可以正常运转甚至及时纠错,不至于瘫痪而使得软件无法运转下去。
发送端: 'By wgscd Dim sendsocket As New Net.Sockets.Socket(Net.Sockets.AddressFamily.InterNetwork,Net.Sockets.SocketType.Stream, Net.Sockets.ProtocolType.Tcp) '实例化socketDim ipendpiont As New Net.IPEndPoint(Net.IPAddress.Parse("127.0.0.1"), 8888) '建⽴终结点'OpenFileDialog1.ShowDialog()Dim fs As New IO.FileStream("c:\wgscd.dat", IO.FileMode.OpenOrCreate, IO.FileAccess.Read) '要传输的⽂件Dim fssize(fs.Length - 1) As ByteDim strread As New IO.BinaryReader(fs) '流处理要传输的⽂件'fs.Read(fssize, 0, fssize.Length - 1)strread.Read(fssize, 0, fssize.Length - 1)sendsocket.Connect(ipendpiont) '连接远程计算机sendsocket.Send(fssize) '发送⽂件Label1.Text = fs.Length()fs.Close()sendsocket.Shutdown(Net.Sockets.SocketShutdown.Send)'关闭发送连接sendsocket.Close() '关闭本机socket 接收端: Dim receivesocket As NewNet.Sockets.Socke(Net.Sockets.AddressFamily.InterNetwork,Net.Sockets.SocketType.Stream,Net.Sockets.ProtocolType.Tcp) Private Sub Form1_Load(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles MyBase.Load Dim hostipendpiont As New Net.IPEndPoint(Net.IPAddress.Parse("127.0.0.1"), 8888) receivesocket.Bind(hostipendpiont) '建⽴远程计算机的的socket receivesocket.Listen(2) '监听socket End Sub Private Sub Button1_Click(ByVal sender As Object,ByVal e As System.EventArgs) Handles Button1.Click Dim recbyte(229888990) As Byte Dim hostsocket As Net.Sockets.Socket = receivesocket.Accept() '同意和发送端计算机建⽴连接 hostsocket.Receive(recbyte) If hostsocket.Receive(recbyte) > 0.1 Then MsgBox("yyyyy" & hostsocket.Receive(recbyte)) End If Dim recfs As New IO.FileStream("c:\wgscd2.dat", IO.FileMode.OpenOrCreate) '接收数据并将其保存到⼀个新的⽂件中 Dim newfilestr As New IO.BinaryWriter(recfs) '流写 'recfs.Write(recbyte, 0, recbyte.Length - 1) newfilestr.Write(recbyte, 0, recbyte.Length - 1) recfs.Close() hostsocket.Shutdown(Net.Sockets.SocketShutdown.Receive) hostsocket.Close() End Sub。
socket完成文件传输的原理
Socket是计算机网络编程中常用的一种通信方式,它通过网络将数据传输到远程主机。
而文件传输则是Socket通信中经常需要实现的功能之一。
实现文件传输的原理如下:
1. 建立Socket连接:在进行文件传输前,需要建立Socket连接。
客户端和服务器之间都需要创建一个套接字(socket),并通过该套接字建立网络连接。
2. 打开文件:在进行文件传输前,需要先打开要传输的文件。
客户端和服务器都需要先打开相应的文件,并且需要知道文件的路径和文件名。
3. 读取文件内容并发送:客户端将要传输的文件读取到内存中,然后通过Socket发送给服务器。
服务器接收客户端发送的数据,并将数据写入到本地硬盘上。
同样地,服务器也可以将要传输的文件读取到内存中,然后通过Socket发送给客户端。
4. 关闭Socket连接和文件:在文件传输完成后,客户端和服务器都需要关闭Socket连接,并且关闭相应的文件。
综上所述,Socket完成文件传输的原理就是通过Socket连接发送文件内容,实现文件传输。
客户端将要传输的文件读取到内存中,并通过Socket发送给服务器,服务器接收到数据后将其写入本地硬盘上。
同样地,服务器也可以将要传输的文件读取到内存中,并通过Socket发送给客户端。
完成文件传输后,客户端和服务器都需要关闭Socket连接和相应的文件。
socket完成文件传输的原理
Socket是一种网络编程的技术,用于在不同的计算机之间进行数据传输和通信。
通过Socket,可以实现文件的上传和下载,从而实现文件的传输。
文件传输的原理是基于TCP/IP协议的。
首先,建立一个TCP连接,然后通过该连接发送和接收数据。
发送端将文件分为若干个数据包,每个数据包的大小可以根据网络状况和传输速度进行调整,然后将这些数据包发送到接收端。
接收端接收到这些数据包后,将它们按照顺序进行组合,最终还原出原始文件。
在文件传输过程中,需要进行错误检测和纠正。
为了保证数据的准确性,发送方需要将每个数据包的校验和一并发送到接收端。
接收端收到数据包后,会进行校验和的计算,如果发现数据包有错误,就会向发送端发送一个重传请求,要求重新发送数据包。
通过这样的方式,可以保证数据的可靠传输。
除了TCP协议之外,还可以使用UDP协议进行文件传输。
UDP协议是一种无状态协议,发送方不会对每个数据包进行确认,也不会进行数据包的重传。
因此,UDP协议的传输速度更快,但是可靠性也会降低。
总的来说,Socket可以实现文件传输的原理是基于TCP/IP协议的,通过建立TCP连接,并对数据进行分包、校验和、重传等多种技术的应用,可以保证文件传输的可靠性和速度。
- 1 -。
´ËʵÀýÊǿͻ§¶ËÏò·þÎñÆ÷¶Ë´«ËÍÎļþ·þÎñÆ÷¶Ë´úÂëʵÏÖ£º#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/stat.h>#include <unistd.h>#include <arpa/inet.h>#include <errno.h>#include <fcntl.h>#define FU_SERVER_PORT 8080 /*set port*/#define FU_BUFFERSIZE 1024 /*set buffer size*/#define FU_LISTENQ 10 /*set listen max conncent*/int main(int argc,char *argv[]){int fu_listenfd,fu_connfd,fu_filefd; /*descriptor*/int fu_read,fu_write;int struct_size;struct sockaddr_in fu_servaddr,fu_cliaddr;char *fu_filename;char *p;char buffer[FU_BUFFERSIZE];fu_listenfd=socket(AF_INET,SOCK_STREAM,0); /*create socket*/if(fu_listenfd==-1){perror("fu_socket");exit(1);}memset(&fu_servaddr,0,sizeof(fu_servaddr)); /*servaddr set 0*/fu_servaddr.sin_family=AF_INET; /*init serveraddr*/fu_servaddr.sin_addr.s_addr=INADDR_ANY;fu_servaddr.sin_port=htons(FU_SERVER_PORT);/*bind fu_listenfd*/if(-1==(bind(fu_listenfd,(struct sockaddr *)&fu_servaddr, sizeof(fu_servaddr)))){exit(1);}/*listen fu_listenfd*/if(-1==(listen(fu_listenfd,FU_LISTENQ))){perror("fu_listen");exit(1);}/*file upload server start*/while(1){printf("file upload server starting......\n");memset(&fu_cliaddr,0,sizeof(fu_cliaddr));struct_size=sizeof(fu_cliaddr);fu_connfd=accept(fu_listenfd,(struct sockaddr *)&fu_cliaddr,&struct_size); if(-1==fu_connfd){perror("fu_accpet");continue;}fu_filename="/root/backup.txt";printf("will upload file name is:%s\n",fu_filename);fu_filefd=open(fu_filename,O_RDWR|O_CREAT|O_TRUNC,S_IRWXU);if (fu_filefd<0) {perror("open localhost file");continue;}while(fu_read=read(fu_connfd,buffer,FU_BUFFERSIZE)) {if (fu_read< 0) {perror("read client file");break;}if (-1==write(fu_filefd,buffer,fu_read)) {perror("writing to filefd error");break;}}if(-1==fu_read||-1==fu_write) continue;close(fu_filefd);printf("file upload success!\n");}close(fu_listenfd);return 0;}¿Í»§¶Ë´úÂëʵÏÖ£º#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>ar#include <sys/socket.h>#include <sys/stat.h>#include <unistd.h>#include <arpa/inet.h>#include <errno.h>#include <fcntl.h>#define FU_SERVER_PORT 8080 /*set port*/#define FU_BUFFERSIZE 1024 /*set buffer size*/int main(int argc,char *argv[]){int fu_sockfd,fu_filefd; /*descriptor*/int fu_read,fu_write;int struct_size;struct sockaddr_in fu_sockaddr;char *fu_filename;char *p;char buffer[FU_BUFFERSIZE];if (argc!=2) {perror("fu_Usage: <./client> <server IP>\n");exit(1);}fu_sockfd=socket(AF_INET,SOCK_STREAM,0); /*create socket*/if(fu_sockfd==-1){perror("fu_socket");exit(1);}memset(&fu_sockaddr,0,sizeof(fu_sockaddr)); /*servaddr set 0*/fu_sockaddr.sin_family=AF_INET; /*init serveraddr*/inet_aton(argv[1],&fu_sockaddr.sin_addr);fu_sockaddr.sin_port=htons(FU_SERVER_PORT);if(-1==(connect(fu_sockfd,(struct sockaddr *)&fu_sockaddr,sizeof(fu_sockaddr)))){ perror("fu_connect");exit(1);}printf("start connecting..........\n");fu_filename="./will.txt";printf("will upload file name is:%s\n",fu_filename);fu_filefd=open(fu_filename,O_RDONLY);if(-1==fu_filefd){perror("open will upload file");exit(1);}while(fu_read=read(fu_filefd,buffer,FU_BUFFERSIZE)){if(-1==fu_read){perror("read will upload file");exit(1);}p=buffer;while(fu_write=write(fu_sockfd,p,fu_read)){if(-1==fu_write){perror("write client file");break;}else if(fu_read==fu_write) break;else if(fu_write>0){p+=fu_write;fu_read-=fu_write;}}if(-1==fu_write) exit(1);}close(fu_filefd);close(fu_sockfd);printf("file already is uploaded!\n");}。
VB中使用WinSock控件传送文件传送文件对于网络编程来说是基本的功能,比如远程控制软件;在编制一个软件时,我从网上下了很多传文件的程序,这些程序提供的传文件功能根本就不能用;传文本还可以,传二进制文件根本就不行;因此,作为一个基本的功能模块,有必要单独介绍一下;首先,在VB中要传送字符串,你可以这样写:DimstrDataAsStringstrData="Test"但是如果你传送的二进制文件,你还能用String变量来存放吗从理论上分析是不行的,我也做了实验,确实是不行的;文件虽然可以传,但是接受的文件和发送的不一样,原因可能是二进制文件里可以有任何"字符",但是不是所有的字符都可以放在String变量里;除了String类型的变量,VB中其他类型的变量都只有几个字节长,难道一次只能发几个字节吗那样岂不是要累死机器了其实,情况没有那么悲观,我们完全可以使用数组来解决这个问题,就是使用byte数组;把要传送的文件都读到数组里,然后发送出去;程序如下:FileName为要传送的文件名,WinS为发送文件的WinSock控件;这是一个发送端的程序;PublicSubSendFileFileNameAsString,WinSAsWinsockDimFreeFAsInteger'空闲的文件号DimLenFileAsLong'文件的长度DimbytDataAsByte'存放数据的数组FreeF=FreeFile'获得空闲的文件号OpenFileNameForBinaryAsFreeFile'打开文件DoEventsLenFile=LOFFreeF'获得文件长度ReDimbytData1ToLenFile'根据文件长度重新定义数组大小GetFreeF,,bytData'把文件读入到数组里CloseFreeF'关闭文件'发送数据EndSub接受端的程序如下:PrivateSubWinsock1_DataArrivalByValbytesTotalAsLong DimbytDataAsByteDimff=FreeFileOpenstrFileNameForBinaryAsfReDimbytData1TobytesTotalPutf,i,bytDatai=i+bytesTotal'保证每次写都是在文件的末尾,i是个全局变量ClosefEndSub这里有两个需要注意的地方,ReDimPreservebytData1ToLenFile,下标是从1开始的,如果你写成ReDimbytDataLenFile,下标就是从0开始了,数组就有LenFile+1长了;LenFile=LOFFreeFile中的LOF是获得文件长度的函数,是VB里带的,我见过很多例子用API,或者循环的读直到末尾来获取文件长度,这样都是很麻烦的,使用LOF 函数就可以了;这样的程序,即可以传送文本文件,也可以传送二进制文件;但是你有没有发现这个程序的问题呢如果我要传送一个50M的文件呢系统可以为bytData分配50M的内存空间吗于是笔者拿一个50M的文件做实验吧,接收到的文件和原来的文件不一样,比原来的大;问题出在那呢首先,根据文件大小重新定义bytData数组的大小本身就有问题,系统是不可能无限制的给数组分配空间的,即使可以,也会造成系统响应变慢;在传50M文件的时候,系统就跟死机了一样;那么怎么解决这个问题呢,一个自然的想法就是把数据分段传送;程序如下:发送程序,iPos是个全局变量,初始值为0;这个变量保存着当前数据的位置;ConstiMax=65535是每个数据块的大小;dimiposaslongConstiMax=65535DimFreeFAsInteger'空闲的文件号DimLenFileAsLong'文件的长度DimbytDataAsByte'存放数据的数组FreeF=FreeFile'获得空闲的文件号OpenFileNameForBinaryAsFreeF'打开文件DoEventsLenFile=LOFFreeF'获得文件长度IfLenFile<=iMaxThen'如果要发送的文件小于数据块大小,直接发送ReDimbytData1ToLenFile'根据文件长度重新定义数组大小GetFreeF,,bytData'把文件读入到数组里CloseFreeF'关闭文件'发送数据ExitSubEndIf'文件大于数据块大小,进行分块发送DoUntiliPos>=LenFile-iMax'发送整块数据的循环ReDimbytData1ToiMaxGetFreeF,iPos+1,bytDataiPos=iPos+iMax'移动iPos,使它指向下来要读的数据Loop'这里要注意的是,必须检查文件有没有剩下的数据,如果文件大小正好等于数据块大小的'整数倍,那么就没有剩下的数据了ReDimbytData1ToLenFile-iPos'发送剩下的不够一个数据块的数据GetFreeF,iPos+1,bytDataCloseFreeF下面是接收端的程序:PrivateSubWinsock1_DataArrivalByValbytesTotalAsLongDimbytDataAsByteDimlLenFileAsLongDimff=FreeFileOpenstrFileNameForBinaryAsf'strFileName是文件名lLenFile=LOFfReDimbytData1TobytesTotalIflLenFile=0Then'lLenFile=0表示是第一次打开文件,这里有个问题,就是'如果如果该文件存在的话,就会出错,应该在打开前检查文件是否存在;这里我省略了Putf,1,bytDataElsePutf,lLenFile+1,bytDataEndIfClosefEndSubVBSOCKET实现文件传输支持断点续传OptionExplicitConstPACKSIZEAsLong=65536'每包大小为64KPrivatefilepathAsStringPrivatefilenameAsStringPrivatefilelengthAsLong'存储文件信息PrivatedataAsBytePrivatepackAsLongPrivatesendedDataAsLong'数据缓冲区,文件包数,已传输的数据PrivatealreadySendAsBooleanPrivatecmsStrAsStringConstfileDAsString="D:\NMSPlugin\source\"PrivateSubcmdConnectClient_Click=sckTCPProtocol==8080'连接客户端EndSubPrivateSubcmdSendFile_ClickOpenfileDForBinaryAs3filename=""filelength=LOF3Close3"NMSP_AYUREADY"EndSubPrivateSubWinsockSend_Connect="已与客户端建立连接;"EndSub'"发送文件"按钮事件代码:PrivateSubsendFileDimiAsIntegerDimjAsLongDimmAsLongfilepath=fileD="向客户端传送文件:"&filename&"大小为:"&filelength'计算需要传输文件的包数pack=filelength-sendedData\PACKSIZEIffilelength-sendedDataModPACKSIZE<>0Thenpack=pack+1EndIfIfpack=0Thenpack=pack+1EndIf'传输文件OpenfilepathForBinaryAs1Fori=1Topack'如果只有一包Ifpack=1Then"filename="&filename&"|filelength="&filelength&"|send="&sendedData ReDimdatafilelength-sendedData'读取数据Forj=sendedData+1TofilelengthGet1,j,dataj-sendedDataNext'更新已传输文件的数据sendedData=filelength'发送文件数据'如果是最后一包ElseIfi+1=packThen'读取最后一包的数据ReDimdatafilelength-sendedDataForj=1Tofilelength-sendedDataGet1,sendedData+j,datajNext'发送文件数据'更新已传输文件的数据sendedData=filelengthExitForElse'将文件数据放到数据缓冲区ReDimdataPACKSIZEForm=1ToPACKSIZEGet1,sendedData+m,datajNext'发送文件数据'更新已传输文件的数据sendedData=sendedData+PACKSIZEEndIf=IntsendedData/filelength100Next=IntsendedData/filelength100Close1alreadySend=FalseEndSub'客户端反馈PrivateSubWinsockSend_DataArrivalByValbytesTotalAsLong DimcmdStrAsString,vbStringIfMidcmdStr,1,13="NMSP_IAMREADY"Then'客户端已准备好接收时,要求客户端报告已经接收的文件大小"NMSP_RPTCURLE"&filenameElseIfMidcmdStr,1,13="NMSP_REQFILEN"Then'客户端要求发送文件名称"NMSP_FILENAME="&filenameElseIfMidcmdStr,1,13="NMSP_REQFILES"Then'客户端要求发送文件大小"NMSP_FILESIZE="&filelength',vbLongElseIfMidcmdStr,1,13="NMSP_RECEIVED"Then'收到客户端已经接收到的文件大小报告"客户端已经接收了"&MidcmdStr,14,LencmdStrsendedData=MidcmdStr,15,LencmdStrIffilelength=sendedDataThen"NMSP_SENDDONE"'初始化文件名,大小,已接收大小,遍历是否还需要向别的客户端发送Letfilename=""Letfilelength=0LetsendedData=0="文件发送完毕"ElseCallsendFileEndIfEndIfEndSub'==========================================================客户端====================================================== OptionExplicitDimflagAsBoolean'设置是否继续接收文件的开关标识PrivatereadyReceiveAsBooleanPrivatefilenameAsStringPrivatetempfileAsStringPrivaterealfileAsStringPrivatereveivePathAsStringPrivatefilelengthAsLong'存储文件信息PrivatedataAsByte,receivedAsLong'声明数据缓冲区和已接收的数据PrivateSubForm_LoadreveivePath=&"\received\"=sckTCPProtocol=8080CallinitReceiveStateEndSubPrivateSubWinsockReceive_Connect="已经连接到服务器"EndSubPrivateSubWinsockReceive_ConnectionRequestByValrequestIDAsLong <>0ThenEndIf="已接受连接请求;"EndSubPrivateSubWinsockReceive_DataArrivalByValbytesTotalAsLong DimjAsLong'分别接收传输文件的文件名、文件长度',vbString,bytesTotal-4',vbLong'判断指令类型IfreadyReceive=FalseThenDimcmdStrAsString,vbStringIfMidcmdStr,1,13="NMSP_AYUREADY"Then'询问是否准备好接收文件Iffilename=""Then"NMSP_REQFILEN"ElseIffilelength=0Then"NMSP_REQFILES"Else"NMSP_IAMREADY"EndIfElseIfMidcmdStr,1,13="NMSP_FILENAME"Then'文件名filename=MidcmdStr,15,LencmdStr"NMSP_REQFILES"ElseIfMidcmdStr,1,13="NMSP_FILESIZE"Then'文件大小filelength=MidcmdStr,15,LencmdStrIffilelength<>0Then"NMSP_IAMREADY"EndIfElseIfMidcmdStr,1,13="NMSP_RPTCURLE"Then'服务器端要求提供已经接收的文件大小'为传输文件设置临时文件realfile=reveivePath&filenametempfile=reveivePath&filename&".td"'返回已接收的数据'OpenrealfileForBinaryAs1OpentempfileForBinaryAs2IfLOF2>0ThenInput2,received"received="&receivedEndIfClose2"NMSP_RECEIVED="&receivedreadyReceive=True="准备接收文件:"&filename&"大小为:"&filelengthElseIfMidcmdStr,1,14="NMSP_SENDDONE="Then'服务器发送文件完毕执行安装操作EndIfElserealfile=reveivePath&filenametempfile=reveivePath&filename&".td"="正在接收文件:"&filename&"保存到:"&realfile'返回已接收的数据OpenrealfileForBinaryAs1OpentempfileForBinaryAs2'建立数据缓冲区ReDimdatabytesTotal'接收服务器端传输的数据,vbArray+vbByte'将接收的数据写入文件Forj=received+1Toreceived+bytesTotalPut1,j,dataj-received-1Put2,j,dataj-received-1Next'更新已接收的数据received=received+bytesTotal '更新临时文件'Write2,received=Intreceived/filelength100 '传输完毕>=100Then="数据传输完毕"Close2'删除临时文件KilltempfileClose1CallinitReceiveStateEndIfClose1Close2EndIfEndSub PrivateSubinitReceiveState readyReceive=Falsereceived=0filelength=0filename=""="监听中"EndSub。