之前问过关于SP123大神关于c# tcp同步通讯+多线程的处理方式.通讯 接收 处理数据 都成功了,http://bbs.csdn.net/topics/391025405但是有一个问题,可能会发生网络掉线或者服务器设备损坏无法发出数据的问题。这个时候可能网线恢复或者设备重新开始工作后 我需要我这边的c# sokcte客户端能够重新连接,以下是我的解决思路,但是这样 数据会发生错位的解析处理,我不知道是不是我的思路不对,还是因为i线程池造成的问题,希望耐心看完代码解答一下 谢谢各位! static void Main(string[] args) { StarMain(); } public static void StarMain() { foreach (Address address in Common.GetAddress()) { ThreadPool.QueueUserWorkItem(h => SocketClient(address.IP, address.Port)); Thread.Sleep(10); } Console.ReadLine(); } /// <summary> /// 程序开始 /// </summary> public static void SocketClient(string host, int port) { try { ByteQueue queue = new ByteQueue(); IPAddress ip = IPAddress.Parse(host); IPEndPoint ipe = new IPEndPoint(ip, port); Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(ipe); Console.WriteLine(ip + " Connected......"); while (true) { //建立缓冲区 byte[] recByte = new byte[4096]; int bytes = socket.Receive(recByte, recByte.Length, 0); //分多次接收 byte[] reallData = new byte[bytes]; Array.Copy(recByte, reallData, reallData.Length); queue.Enqueue(reallData); //while可处理同时接收到多个包 防止一帧数据不是完整的包 while (queue.Find()) { byte[] readBuffer = queue.Dequeue(); //解析雷达数据 包含平均速度/占有率/车流量 string data = BitConverter.ToString(readBuffer); if (data.StartsWith("FF-FF-FF-FF-CA-CB-CC-CD") && data.EndsWith("EA-EB-EC-ED")) { GetData(data, host, port, DateTime.Now); } else if (data.StartsWith("0A 0B 0C 0D") && data.EndsWith("EA EB EC ED"))//历史数据 { Regex regex = new Regex("0A 0B 0C 0D.{21}"); MatchCollection matches = regex.Matches(data, 0); if (matches.Count > 0) { foreach (Match nextmach in matches) { string history = nextmach.Value; string[] strTime = history.Split("" ""); string year = strTime[0] + strTime[1]; string moth = strTime[2]; string day = strTime[3]; string hh = strTime[4]; string mm = strTime[5]; string ss = strTime[6]; DateTime time = Convert.ToDateTime(year + "-" + moth + "-" + day + " " + hh + ":" + mm + ":" + ss); GetData(data, host, port, time); } } } else { Console.WriteLine(data); } } } } catch (ArgumentNullException e) { Console.WriteLine("ArgumentNullException: {0}", e.Message); } catch (SocketException e) { Console.WriteLine("SocketException: {0}", e.Message); System.Timers.Timer t = new System.Timers.Timer(1000); //实例化Timer类,设置间隔时间为10000毫秒; t.Elapsed += new System.Timers.ElapsedEventHandler(theout); //到达时间的时候执行事件; t.AutoReset = true; //设置是执行一次(false)还是一直执行(true); t.Enabled = true; //是否执行System.Timers.Timer.Elapsed事件; } } public static void theout(object source, System.Timers.ElapsedEventArgs e) { StarMain(); } |
|
同步或者异步对的客户端来说有什么区别呢?
或者是服务端根本没区别…所以你完全没必要纠结 我非得用同步+线程这样的方法.. 因为异步比你这个高效的不是一个次元. ———————————– 本问题中..你是客户端还是服务端? 如果是客户端,你这代码是运行在你的”设备”中的?如果是这样try catch就可以捕获到”你”掉线或者”他”掉线. 掉线之后丢一个timer重新连接即可. 如果是服务端,客户端掉线你能捕获..你也只能捕获而已……. ————————————– 从你的代码来看是有问题的..因为一旦掉线之后 会1s出来一个timer 而且成倍的增长…1-2-4-8-16….. 所以要保证一个timer执行一次就释放了..或者只执行一次.. ————————————- 另外顺便问下 你这是一个客户端连接N个服务端? |
|
没我出场,看来就不行了! 把这个部份代码 抽出来,弄个一个方法 不要用 while (true) 去执行,应用异步 如果你坚持要用while true 那你上面的代码要改一下,不要再用时间去整这个。就是 int bytes = socket.Receive(recByte, recByte.Length, 0); 这个接收为0或内部出异常时,要结束while true 然后再延迟N秒进行重连。明白了么小明哥。 //建立缓冲区 byte[] recByte = new byte[4096]; int bytes = socket.Receive(recByte, recByte.Length, 0); //分多次接收 byte[] reallData = new byte[bytes]; Array.Copy(recByte, reallData, reallData.Length); queue.Enqueue(reallData); //while可处理同时接收到多个包 防止一帧数据不是完整的包 while (queue.Find()) { byte[] readBuffer = queue.Dequeue(); //解析雷达数据 包含平均速度/占有率/车流量 string data = BitConverter.ToString(readBuffer); if (data.StartsWith("FF-FF-FF-FF-CA-CB-CC-CD") && data.EndsWith("EA-EB-EC-ED")) { GetData(data, host, port, DateTime.Now); } else if (data.StartsWith("0A 0B 0C 0D") && data.EndsWith("EA EB EC ED"))//历史数据 { Regex regex = new Regex("0A 0B 0C 0D.{21}"); MatchCollection matches = regex.Matches(data, 0); if (matches.Count > 0) { foreach (Match nextmach in matches) { string history = nextmach.Value; string[] strTime = history.Split("" ""); string year = strTime[0] + strTime[1]; string moth = strTime[2]; string day = strTime[3]; string hh = strTime[4]; string mm = strTime[5]; string ss = strTime[6]; DateTime time = Convert.ToDateTime(year + "-" + moth + "-" + day + " " + hh + ":" + mm + ":" + ss); GetData(data, host, port, time); } } } else { Console.WriteLine(data); } } |
|
枪炮,你这是异步的方式,我上面是同步加多线程的处理啊
对 是的 一个客户端对应N个服务器 由于网络环境局限 只能按照这种模式。 |
|
异步我用过了 某些方面有局限 这种方式满足我的需求 不太懂你说的意思- -! |
|
40分 |
…你的需求与同步没有关系的。是你的代码方式的问题。 |
30分 |
线程是相当宝贵的资源。我的电脑创建2000个线程就到头了。
int bytes = socket.Receive(recByte, recByte.Length, 0);//这个地方楼上说了,要判断0的问题。 看你的代码粘包根本没有做处理。网络不堵塞的情况下还可以,如果出现堵塞。你根本收不到你想要的数据。 |
30分 |
我一般另开个线程监视socket运行状态,如果状态不对,我就释放资源从新建立socket
不知道是否这个思路太过奔放 |
字符串判断 和字节判断 服务器配置可以的 不考虑 再说这样做 测试过没有出现什么大问题 你的意思是说 直接用字节判断吧? |
|
还有 粘包是在Queue类中处理的 |