C#网络编程之TCP(六)
一、大文件的上传
上一章节我们了解了小文件在客户端和服务器之间是如何传输的。但对于一个几百兆或者几个G大文件来说,无法通过一次传送,就能够把文件的所有数据都传过去。所以我们要制定一个多回合的传输方式,每次发送较小的数据包,传输完成后生成一个完整的文件。
二、简单的例子
客户端
const string ip = "127.0.0.1"; const int port = 10002; Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); EndPoint point = new IPEndPoint(IPAddress.Parse(ip), port); socket.Connect(point); Console.WriteLine("链接至服务器..."); // 文件路径 string path = @"D:/TempFile/HelloWorld.zip"; using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { byte[] bytes = new byte[1024 * 8]; while (true) { int n = fs.Read(bytes); if (n <= 0) break; Console.WriteLine(">> 发送的数据大小: " + n); // 先发送内容的长度 byte[] buf = new byte[4]; ConvertIntToByteArray(n, ref buf); socket.Send(buf); // 再发送内容 socket.Send(bytes); } Console.WriteLine("发送完毕"); socket.Close(); }
服务端
const string ip = "127.0.0.1"; const int port = 10002; // 建立服务器 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); EndPoint point = new IPEndPoint(IPAddress.Parse(ip), port); socket.Bind(point); socket.Listen(); // 监听客户端发起连接 Socket conn = socket.Accept(); Console.WriteLine("有客户端连接..."); Thread.Sleep(1000); // 临时文件名 string fileSavePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory) + "upload.zip"; using (FileStream fs = new FileStream(fileSavePath, FileMode.OpenOrCreate, FileAccess.Write)) { while (true) { // 接收数据 byte[] bytes = new byte[4]; // 先获取内容长度 conn.Receive(bytes); int len = BitConverter.ToInt32(bytes, 0); if (len <= 0) { conn.Close(); Console.WriteLine("接收完毕"); break; } Console.WriteLine("接收的数据大小: " + len); byte[] dataBuffer = new byte[len]; // 再获取内容 conn.Receive(dataBuffer); fs.Write(dataBuffer, 0, len); } }
运行客户端程序和服务端程序,将指定目录下得文件传输至服务器。可以看到双方都通过多次的传输,最终完整的发送和接收了数据。
打开服务器端接收过来的数据,并将其解压后打开。可以验证,文件完好无损的被传输了过去。
本次的demo比较简单,实际传输过程我们还需要将文件的名字也读取过来,这样能方便的分辨文件的类型了。