一.小结
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(); } } }