socket 的链接粘包的问题
---恢复内容开始---
前边两个是服务器的
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Socket1 8 { 9 class Message 10 { 11 private byte[] data = new byte[1024]; 12 private int starIndex = 0;//剩余长度 13 14 public byte[] Data { get => data; set => data = value; } 15 public int StarIndex { get => starIndex; set => starIndex = value; } 16 17 public int RemainSize//剩余空间大小 18 { 19 get { return data.Length - starIndex; } 20 } 21 public void AddCount(int count)//每次得到新的数据 就更新StartIndex 22 { 23 starIndex += count; 24 } 25 26 public void ReadMassage() 27 { 28 while (true) 29 { 30 if (StarIndex<=4) 31 { 32 return; 33 } 34 int count = BitConverter.ToInt32(data, 0);//第一段数据的长度 35 if (StarIndex-4>=count) 36 { 37 string s= Encoding.UTF8.GetString(data,4,count); 38 Console.WriteLine("解析到一条数据"+s); 39 40 Array.Copy(data,count+4,data,0,StarIndex-4-count); 41 StarIndex -= (count + 4); 42 } 43 else 44 { 45 break; 46 } 47 } 48 } 49 } 50 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Net; 5 using System.Net.Sockets; 6 using System.Text; 7 using System.Threading.Tasks; 8 9 10 namespace Socket1 11 { 12 class Program 13 { 14 static void Main(string[] args) 15 { 16 StartServer(); 17 Console.ReadKey(); 18 } 19 static void StartServer() 20 { 21 Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); 22 IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); 23 IPEndPoint iPEndPoint = new IPEndPoint(ipAddress,1234); 24 server.Bind(iPEndPoint); 25 26 server.Listen(0);//开始监听 27 28 //Socket clientSocket= server.Accept(); 29 30 server.BeginAccept(AcceptCallBack,server); 31 } 32 static void AcceptCallBack(IAsyncResult ar) 33 { 34 Socket server=ar.AsyncState as Socket; 35 Socket clientSocket=server.EndAccept(ar); 36 37 string msg = "恭喜你连接成功"; 38 byte[] data = Encoding.UTF8.GetBytes(msg); 39 clientSocket.Send(data); 40 41 //异步接收 42 dataBuffer = new byte[1024]; 43 clientSocket.BeginReceive(message.Data, message.StarIndex,message.RemainSize , SocketFlags.None, ReceiveCallBack, clientSocket); 44 server.BeginAccept(AcceptCallBack, server); 45 } 46 static Message message = new Message(); 47 static byte[] dataBuffer = new byte[1024]; 48 static void ReceiveCallBack(IAsyncResult ar) 49 { 50 //检测数据接收结束 51 Socket clientSocket=null; 52 try 53 { 54 clientSocket = ar.AsyncState as Socket; 55 int count = clientSocket.EndReceive(ar); 56 if (count==0) 57 { 58 clientSocket.Close(); 59 return; 60 } 61 message.AddCount(count); 62 message.ReadMassage(); 63 clientSocket.BeginReceive(message.Data, message.StarIndex, message.RemainSize, SocketFlags.None, ReceiveCallBack, clientSocket); 64 } 65 catch (Exception e) 66 { 67 clientSocket.Close(); 68 Console.WriteLine(e.Message); 69 } 70 71 //重复接收 72 } 73 } 74 }
1 using System; 2 using System.Net; 3 using System.Net.Sockets; 4 using System.Text; 5 6 namespace 客户端1 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 Socket clientSokcet = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); 13 14 clientSokcet.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"),1234)); 15 16 byte[] data = new byte[1024]; 17 int count = clientSokcet.Receive(data); 18 string msg = Encoding.UTF8.GetString(data, 0, count); 19 System.Console.WriteLine(msg); 20 21 //while (true) 22 //{ 23 // string s = Console.ReadLine(); 24 // if (s == "a") 25 // { 26 // clientSokcet.Close(); 27 // return; 28 // } 29 // clientSokcet.Send(Encoding.UTF8.GetBytes(s)); 30 //} 31 for (int i = 0; i < 100; i++) 32 { 33 clientSokcet.Send(Message.GetByte(i.ToString())); 34 } 35 //数据的粘包 36 37 38 Console.ReadKey(); 39 } 40 } 41 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 客户端1 8 { 9 class Message 10 { 11 public static byte[] GetByte(string data) 12 { 13 byte[] dataByte= Encoding.UTF8.GetBytes(data);//数据 14 int dataLength= dataByte.Length; 15 byte[] lengthBytes= BitConverter.GetBytes(dataLength); 16 17 byte[] newByte=lengthBytes.Concat(dataByte).ToArray(); 18 19 return newByte; 20 } 21 } 22 }
一。这个是服务器
创建一个socket 地址,传输方式(流的方式),协议类型
本地ip地址的写法:
绑定ip地址和端口号:
监听:多少秒钟监听一次
持续监听:
客户端的socket:
给客户端发送消息:
总的客户端发送消息:
服务器接受:
异步接受的方式
//字节类型,从头开始存,代表接收的长度,枚举类型的(接收和发送数据的行为),需要一个回调函数(一个方法),回调函数 的参数(把服务器给他传入)
回调方法接收的时候必须是这个类型的值
转换数据类型
所有接收到数据的长度:
存起来:
每次接收完 再调用自己:
———————————————————————————————————————————
二。这个号是客户端
创建。链接:
接收:
穿消息给服务器断筋:
服务器可以重复接收客户端消息:
如何实现多个客户端链接服务器?
不用这个同步接收的方式,
改用异步接收:
还需要一个异步接收客户端消息方法:
在方法里拿到服务器:
调用服务器里的结束,接收到的就是客户端:
同步接收消息
客户端发送消息的重复接收 链接的重负:
接收消息是只有一个
有时候对的:
客户端关闭服务器错误的问题?
改正方式:
客户端非正常的关闭???
如果你输入的值等于某个数字的时候,关闭.
这样的话一直死循环:
也即是它一直还在这个地方,才一直循环
改正方法,如果接收的数据字节只有0个:
---恢复内容结束---
---恢复内容开始---
一。这个是服务器
创建一个socket 地址,传输方式(流的方式),协议类型
本地ip地址的写法:
绑定ip地址和端口号:
监听:多少秒钟监听一次
持续监听:
客户端的socket:
给客户端发送消息:
总的客户端发送消息:
服务器接受:
异步接受的方式
//字节类型,从头开始存,代表接收的长度,枚举类型的(接收和发送数据的行为),需要一个回调函数(一个方法),回调函数 的参数(把服务器给他传入)
回调方法接收的时候必须是这个类型的值
转换数据类型
所有接收到数据的长度:
存起来:
每次接收完 再调用自己:
———————————————————————————————————————————
二。这个号是客户端
创建。链接:
接收:
穿消息给服务器断筋:
服务器可以重复接收客户端消息:
如何实现多个客户端链接服务器?
不用这个同步接收的方式,
改用异步接收:
还需要一个异步接收客户端消息方法:
在方法里拿到服务器:
调用服务器里的结束,接收到的就是客户端:
同步接收消息
客户端发送消息的重复接收 链接的重负:
接收消息是只有一个
有时候对的:
客户端关闭服务器错误的问题?
改正方式:
客户端非正常的关闭???
如果你输入的值等于某个数字的时候,关闭.
这样的话一直死循环:
也即是它一直还在这个地方,才一直循环
改正方法,如果接收的数据字节只有0个:
应该是接收一百次,可是一次就接收完了
这种只有TCp有的特征,发现你发的这个是小数据 就一次性了,就叫数据的粘包
要解决这个问题:
发消息的时候,不发字节 发数组,把长度和数据一起放包里发送
添加一个新类 专门处理这个消息:
把消息传进来,
先转换数据
再去获得他的长度,
把长度也转换为字节:
整数类型永远占用4个字节
再来一个数组把 数据长度 数组长度结合起来,(数组长度在前 数据在后)
到客户端的时候就不直接发送tostring了,而是
服务器解析消息的时候也的改变
服务器也添加新类:
先解析前四个字节 再往后 然后
添加一个数组 接收一下:
一个新的方法,去解析粘包的数据,一直解析,直到发现接收的数组小于4,就不解析了
没有数据不解析了
转换数据类型为int类型,
从4的位置开始解析,
第一条信息就解析出来了
把解析出来的第一条数据砍掉,放到一个新的数组里面去,
从数据的长度,加上四的长度:
复制剩余的长度=总长-4-第一条长
添加属性:
剩余的长度的方法:
剩余长度=总长度-用过的长度:
每次得新的长度 ,加起来:
类写完 到服务器里更新
不能用以前的解析了,
存如这个数组里面
从哪里开始从 从已经存的长度开始存,
能存多长(还能存类的方法)
解析也饿的换:
首先更新message里面的数据,
再用法法
上边就是完整的了
最难的就是这里了
---恢复内容结束---