如何通过Socket TCP发送并接收一个文件

发布网友 发布时间:2022-04-21 17:43

我来回答

1个回答

热心网友 时间:2022-04-22 09:10

  一.小结

  1.大包发小包收,只发一次。

  2.发时把文件扩展名,文件长度也随同一起发送,方便接收端接收时另存为正确的文件类型,并判断是否已经接收完毕。

  如果不一起发送,分为文件扩展名,文件长度,文件内容,发送三次,在接收端,也可能会一起收到,反而不利于解析。

  

  二.客户发送端代码

  

  复制代码
  private void btnSend_Click(object sender, EventArgs e)
  {
  //组合出远程终结点
  IPAddress ipAddress = IPAddress.Parse(this.txtIP3.Text);
  IPEndPoint hostEP = new IPEndPoint(ipAddress, Convert.ToInt32(this.txtPort3.Text));
  Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  try
  {
  socket.Connect(hostEP);

  //1.发送用户协议
  string path1 = Environment.CurrentDirectory; //获取应用程序的当前工作目录。
  string doc = "YourSendFile.pdf";
  string path = Path.Combine(path1, doc);
  FileStream fs = File.Open(path, FileMode.Open);

  //文件内容
  byte[] bdata = new byte[fs.Length];
  fs.Read(bdata, 0, bdata.Length);
  fs.Close();
  
  //文件扩展名,固定3字节
  byte[] fileExtArray = Encoding.UTF8.GetBytes(string.Format("{0:D3}", currentDocExt));

  //文件长度, 固定为20字节,前面会自动补零
  byte[] fileLengthArray = Encoding.UTF8.GetBytes(bdata.Length.ToString("D20"));
  
  //合并byte数组
  byte[] fileArray = CombomBinaryArray(fileExtArray, fileLengthArray);

  //合并byte数组
  byte[] bdata1 = CombomBinaryArray(fileArray, bdata);

  //发文件长度+文件内容
  socket.Send(bdata1, bdata1.Length, 0);

  //2.接收
  //声明接收返回内容的字符串
  string recvStr = "";

  //声明字节数组,一次接收数据的长度为 1024 字节
  byte[] recvBytes = new byte[1024];

  //返回实际接收内容的字节数
  int bytes = 0;

  //循环读取,直到接收完所有数据
  while (true)
  {
  bytes = socket.Receive(recvBytes, recvBytes.Length, 0);
  //读取完成后退出循环
  if (bytes <= 0) break;

  //将读取的字节数转换为字符串
  recvStr += Encoding.UTF8.GetString(recvBytes, 0, bytes);
  }

  //禁用 Socket
  socket.Shutdown(SocketShutdown.Both);

  //关闭 Socket
  socket.Close();

  //... do some busness logic ...

  }
  catch (Exception e1)
  {
  throw e1;
  }
  }
  复制代码
  

  三.服务接收端代码

  复制代码
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Net.Sockets;
  using System.Net;
  using System.Xml;
  using System.Configuration;
  using System.Windows.Forms;
  using System.IO;

  namespace ConsoleAppServer
  {
  class Program
  {
  [STAThread]
  static void Main(string[] args)
  {
  
  bool Done = false;
  IPAddress ipAddress = IPAddress.Parse(ConfigurationSettings.AppSettings["IP"].ToString());
  IPEndPoint hostEP = new IPEndPoint(ipAddress, Convert.ToInt32(ConfigurationSettings.AppSettings["Port"]));
  Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  socket.Bind(hostEP);
  socket.Listen(3);
  while (!Done)
  {
  Console.WriteLine("waiting for client");

  Socket client = socket.Accept();

  Console.WriteLine("connected client");

  //1.接收
  //声明字节数组,一次接收数据的长度为 1024 字节
  byte[] recvBytes = new byte[1024];
  //返回实际接收内容的字节数
  int bytes = 0;
  
  int FileLength = 0; // 900866;
  int ReceivedLength = 0;

  //1.0 接收文件扩展名
  bytes = client.Receive(recvBytes, 3, 0);
  string fileExt = Encoding.UTF8.GetString(recvBytes, 0, bytes);

  string vFilePath = Environment.CurrentDirectory;
  string vFileName = vFilePath + "\\Tmp" + Guid.NewGuid().ToString() + "." + fileExt;

  //创建文件流,然后让文件流来根据路径创建一个文件
  FileStream fs = new FileStream(vFileName, FileMode.Create);

  //1.1 接收文件长度
  bytes = client.Receive(recvBytes, 20, 0);
  //将读取的字节数转换为字符串
  string fileLength = Encoding.UTF8.GetString(recvBytes, 0, bytes);
  FileLength = Convert.ToInt32(fileLength);

  //1.2接收文件内容
  while (ReceivedLength < FileLength)
  {
  bytes = client.Receive(recvBytes, recvBytes.Length, 0);
  ReceivedLength += bytes;
  fs.Write(recvBytes, 0, bytes);
  }

  fs.Flush();
  fs.Close();

  //... do some business logic ...
  string returnData = SomeBusinessLogic();

  //2.发送
  byte[] bdata = Encoding.UTF8.GetBytes(returnData);
  client.Send(bdata, bdata.Length, 0);

  client.Close();
  }

  socket.Shutdown(SocketShutdown.Both);
  socket.Close();
  }
  
  }
  }

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com