java socket 防止粘包_解决Socket通信中,经常遇到的问题——数据粘包的两种方法...

本文档展示了如何防止Java Socket通信中的数据粘包问题,通过两种方法实现:1) 将所有消息放入一个字符串并加上首尾标记一次性发送;2) 发送前先告知客户端消息长度。代码示例详细解释了这两个方法的实现过程。
摘要由CSDN通过智能技术生成

1 usingSystem;2 usingSystem.Collections.Generic;3 usingSystem.Linq;4 usingSystem.Text;5 usingSystem.Net;6 usingSystem.Net.Sockets;7 usingSystem.Collections;8 usingSystem.Diagnostics;9

10 namespace_07发送变长消息的方法11 {12 classProgram13 {14 static void Main(string[] args)15 {16 #region 先将发送的消息带上首尾标记< > 再将要发送的所有消息,放在一个字符串中 然后一次性发送给客户端

17 DateTime start = DateTime.Now;//记录程序的运行时间

18 string str = null;19 double[] test = { 10.3, 15.2, 25.3, 13.338, 25.41, 0.99, 2017, 20000, 1, 3, 2, 5, 8, 90, 87, 33, 55, 99, 100};20 IPEndPoint IPep2 = new IPEndPoint(IPAddress.Any, 127);21 Socket newsock2 = newSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);22 newsock2.Bind(IPep2);23 newsock2.Listen(10);24 Console.WriteLine("等待新客户端的连接");25 Socket client2 = newsock2.Accept();//等待客户端的连接

26 IPEndPoint clientep2 =(IPEndPoint)client2.RemoteEndPoint;27 Console.WriteLine("与{0}连接在{1}端口", clientep2.Address, clientep2.Port);28 string welcome2 = "welcome to the new server";29 byte[] data;30 str += SpecialMessage(welcome2);//将要发送的消息,都放在字符串str中31

32 //发送数组的长度信息 给字符串str

33 str +=SpecialMessage(test.Length.ToString());34

35 //用循环的形式 依次将数组中的元素给str

36 string[] strvalue = new string[test.Length];37 for (int j = 0; j < test.Length; j++)38 {39 strvalue[j] = test[j].ToString();//将实际速度集合转换为string数组

40 str +=SpecialMessage(strvalue[j]);41 }42

43 //将所有发送的信息,都放在了str中,然后一次性的发送过去 注意都是有首尾标记的消息< >

44 data =System.Text.Encoding.ASCII.GetBytes(str);45 client2.Send(data);46

47 DateTime end =DateTime.Now;48 TimeSpan span = end -start;49 double seconds =span.TotalSeconds;50 Console.WriteLine("程序运行的时间是{0}s", seconds);51

52

53 Console.WriteLine("传送数据成功!");54 client2.Close();//释放资源

55 newsock2.Close();56 Console.ReadKey();57 #endregion

58

59

60 #region 采用变长的消息 即发送时先告诉客户端 消息的长度是多少

61 //DateTime start = DateTime.Now;62 //double[] test = { 10.3, 15.2, 25.3, 13.338, 25.41, 0.99, 2017, 20000, 1, 3, 2, 5, 8, 90, 87, 33, 55, 99, 100 };63 //IPEndPoint IPep2 = new IPEndPoint(IPAddress.Any, 127);64 //Socket newsock2 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);65 //newsock2.Bind(IPep2);66 //newsock2.Listen(10);67 //Console.WriteLine("等待新客户端的连接");68 //Socket client2 = newsock2.Accept();//等待客户端的连接69 //IPEndPoint clientep2 = (IPEndPoint)client2.RemoteEndPoint;70 //Console.WriteLine("与{0}连接在{1}端口", clientep2.Address, clientep2.Port);71 //string welcome2 = "welcome to the new server";72 //byte[] date = Encoding.ASCII.GetBytes(welcome2);//字符串转换为字节数组 传送给客户端73 //SendVarMessage(client2, date);

74

75

76 发送数组的长度信息 给客户端

77 //date = Encoding.ASCII.GetBytes(test.Length.ToString());78 //SendVarMessage(client2, date);

79

80 用循环的形式 依次将数组中的元素发送给客户端

81 //string[] strvalue = new string[test.Length];82 //for (int j = 0; j < test.Length; j++)83 //{84 //strvalue[j] = test[j].ToString();//将实际速度集合转换为string数组85 //date = Encoding.ASCII.GetBytes(strvalue[j]);//string数组中的每个元素一次转换为字节 发送给客户端86 //SendVarMessage(client2, date);87 //}88

89 //DateTime end = DateTime.Now;90 //TimeSpan span = end - start;91 //double seconds = span.TotalSeconds;92 //Console.WriteLine("程序运行的时间是{0}s", seconds);93

94 //Console.WriteLine("传送数据成功!");95 //client2.Close();//释放资源96 //newsock2.Close();97 //Console.ReadKey();

98 #endregion

99 }100

101 ///

102 ///发送变长消息方法103 ///

104 ///

105 ///

106 /// 不需要返回值

107 private static void SendVarMessage(Socket s, byte[] msg)108 {109 int offset = 0;110 intsent;111 int size =msg.Length;112 int dataleft =size;113 byte[] msgsize = new byte[2];114

115 //将消息的尺寸从整型转换成可以发送的字节型116 //因为int型是占4个字节 所以msgsize是4个字节 后边是空字节

117 msgsize =BitConverter.GetBytes(size);118

119 //发送消息的长度信息120 //之前总是乱码出错 客户端接收到的欢迎消息前两个字节是空 后边的两个字符er传送到第二次接收的字节数组中121 //因此将er字符转换为int出错 这是因为之前在Send代码中,是将msgsize整个字节数组发送给客户端 所以导致第3 4个空格也发送122 //导致发送的信息混乱 这两个空格使发送的信息都往后挪了两个位置 从而乱码

123 sent = s.Send(msgsize, 0, 2, SocketFlags.None);124 while (dataleft > 0)125 {126 int sent2 =s.Send(msg, offset, dataleft, SocketFlags.None);127 //设置偏移量

128 offset +=sent2;129 dataleft -=sent2;130 }131 }132

133

134

135 ///

136 ///给发送的消息 加特殊结束标记 头尾分别加""137 ///

138 ///

139 ///

140 private static string SpecialMessage(stringstr)141 {142 string strNew = "";145 returnstrNew;146 }147 }148 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值