我现在有一个winform的服务端程序,调试助手,以及终端设备。
1 using CommonTool; 2 using DevGPSPlatform.Parser; 3 using System; 4 using System.Collections.Generic; 5 using System.Net; 6 using System.Net.Sockets; 7 using System.Text; 8 using System.Threading; 9 using System.Windows.Forms; 10 11 namespace DevGPSPlatform 12 { 13 public partial class Form1 : Form 14 { 15 public Form1() 16 { 17 InitializeComponent(); 18 } 19 public delegate void ShowMessageHandler(string message); 20 private static Socket listenSocket; 21 private static Socket skConnP; 22 private static Socket skCommu; 23 private static Socket skCommuP; 24 private Dictionary<string, Socket> _dict = new Dictionary<string, Socket>(); 25 private void btnStart_Click(object sender, EventArgs e) 26 { 27 try 28 { 29 if (listenSocket == null) 30 { 31 listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 32 listenSocket.Bind(new IPEndPoint(IPAddress.Parse(txtIPAddress.Text), int.Parse(txtPort.Text))); 33 listenSocket.Listen(10); 34 } 35 btnStart.Enabled = false; 36 ShowMessage("启动监听。"); 37 GetTheadList(); 38 } 39 catch (Exception ex) 40 { 41 LogHelper.Instance.Error(DateTime.Now.ToString("HH:mm:ss fff") + "--[程序出错]" + ex); 42 } 43 } 44 45 private void btnStop_Click(object sender, EventArgs e) 46 { 47 try 48 { 49 btnStart.Enabled = true; 50 DestroySocket(); 51 ShowMessage("停止监听。"); 52 } 53 catch (Exception ex) 54 { 55 LogHelper.Instance.Error(DateTime.Now.ToString("HH:mm:ss fff") + "--[程序出错]" + ex); 56 } 57 } 58 private static ManualResetEvent TimeoutObject = new ManualResetEvent(false); 59 private void GetTheadList() 60 { 61 try 62 { 63 //开启一个新线程不断接受用户的连接请求 64 ThreadPool.QueueUserWorkItem(new WaitCallback(skObj => 65 { 66 skConnP = skObj as Socket; 67 //通过循环不断接受用户的连接请求 68 while (true) 69 { 70 //阻塞线程,等待用户的连接请求;每次只能连接一个,到处理到下面线程开启 71 //接收用户消息,那么重新等待;因为新开的线程不阻塞这里,本来线程不用等待 72 skCommu = skConnP.Accept(); 73 //获取客户端信息 74 string userinfo = skCommu.RemoteEndPoint.ToString(); 75 ShowMessage(DateTime.Now.ToString("HH:mm:ss fff") + "--[" + userinfo + "]连接成功"); 76 77 lstUser.Invoke(new Action<string>(u => 78 { 79 lstUser.Items.Add(u); 80 }), userinfo); 81 if (!_dict.ContainsKey(userinfo)) 82 { 83 _dict.Add(userinfo, skCommu); 84 } 85 86 //再启动一个线程来循环接收用户发来的消息 87 ThreadPool.QueueUserWorkItem(new WaitCallback(skCommuObj => 88 { 89 //启动该线程用来处理客户端不断发来的消息,用单独线程来执行 90 //while-true循环,防止阻塞主线程。主线程要继续执行调用Accept()的方法,来接收其他的客户端连接。 91 skCommuP = skCommuObj as Socket; 92 while (true) 93 { 94 try 95 { 96 byte[] buffers = new byte[1024 * 1024 * 2]; 97 // //返回值表示实际接收到的字节数;这儿会阻塞线程,不会走,所以程序不会死;跟BlockingCollection<> 一样 98 skCommuP.ReceiveBufferSize = 8192; 99 int totalNumberOfBytes = 0; 100 101 int len = skCommuP.Receive(buffers, totalNumberOfBytes, skCommuP.ReceiveBufferSize, SocketFlags.None); 102 103 if (len == 0 || !skCommuP.Connected) 104 { 105 if (_dict.ContainsKey(userinfo)) 106 { 107 _dict.Remove(userinfo); 108 } 109 if (skCommuP == Gloable.skWebComm) 110 Gloable.skWebComm = null; 111 if (Gloable._dicWebId.ContainsKey(skCommuP)) 112 { 113 SendDataToWeb.SendData(skCommuP, Gloable.LoginOut, "退出登录"); 114 Gloable._dicWebId.Remove(skCommuP); 115 } 116 if (Gloable._dictId.ContainsKey(skCommuP)) 117 { 118 SendDataToWeb.SendData(skCommuP, Gloable.LoginOut, "退出登录"); 119 Gloable._dictId.Remove(skCommuP); 120 } 121 122 //当客户端退出以后,在log文本框中显示用户退出的信息 123 ShowMessage(DateTime.Now.ToString("HH:mm:ss fff") + "--[" + skCommuP.RemoteEndPoint.ToString() + "]退出了。"); 124 125 //从ListBox中删除当前用户 126 lstUser.Invoke(new Action<string>(x => 127 { 128 lstUser.Items.Remove(x); 129 }), skCommuP.RemoteEndPoint.ToString()); 130 131 132 break; 133 } 134 else 135 { 136 string userMessage = Concat.ToHexString2(buffers, len); 137 138 string str = DateTime.Now.ToString("HH:mm:ss fff") + "--[" + skCommuP.RemoteEndPoint.ToString() + "]接收:" + userMessage; 139 LogHelper.Instance.Info(str); 140 ShowMessage(str); 141 142 if (buffers[0] == 0x78 && buffers[1] == 0x78 && buffers[len - 2] == 0x0D && buffers[len - 1] == 0x0A) 143 { 144 PacketParser(buffers, len, skCommuP); 145 buffers = null; 146 } 147 else if (buffers[0] == 0x3D && buffers[1] == 0x3D) 148 { 149 InstructHandlerParser.WebToServerInstruct(buffers, len, skCommuP); 150 buffers = null; 151 } 152 } 153 } 154 catch (Exception ex) 155 { 156 skCommuP.Shutdown(SocketShutdown.Both); 157 skCommuP.Close(); 158 } 159 } 160 }), skCommu); 161 162 } 163 }), listenSocket); 164 165 Thread replacementThread = new Thread(new ThreadStart(ReplacementToWeb)); 166 replacementThread.Start(); 167 168 } 169 catch (Exception ex) 170 { 171 LogHelper.Instance.Error(DateTime.Now.ToString("HH:mm:ss fff") + "--[程序出错]" + ex); 172 } 173 } 174 public void ReplacementToWeb() 175 { 176 FileInfo.Read(); 177 Thread.Sleep(1000 * 60); 178 } 179 180 public void PacketParser(byte[] buffers, int len, Socket skCommuP) 181 { 182 if (buffers.Length > 3) 183 { 184 switch (buffers[3]) 185 { 186 case 0x01: 187 LoginHandlerParser.LoginParser(buffers, len, skCommuP); 188 break; 189 case 0x22: 190 PositionHanderParser.PositionParser(buffers, len, skCommuP); 191 break; 192 case 0x13: 193 HeartbeatHandlerParser.HeartParser(buffers, len, skCommuP); 194 break; 195 case 0x15: 196 InstructHandlerParser.InstructParser(buffers, len, skCommuP); 197 break; 198 case 0x26: 199 AlarmHandlerParser.AlarmParser(buffers, len, skCommuP); 200 break; 201 } 202 } 203 } 204 205 private static void DestroySocket() 206 { 207 try 208 { 209 if (listenSocket != null) 210 listenSocket.Close(); 211 if (skConnP != null) 212 skConnP.Close(); 213 if (skCommu != null) 214 skCommu.Close(); 215 if (skCommuP != null) 216 skCommuP.Close(); 217 } 218 catch (SocketException ex) 219 { 220 listenSocket.Close(); 221 LogHelper.Instance.Error(DateTime.Now.ToString("HH:mm:ss fff") + "--[程序出错]" + ex); 222 } 223 finally 224 { 225 listenSocket = null; 226 } 227 } 228 public void ShowMessage(string message) 229 { 230 if (lstMsg.InvokeRequired) 231 { 232 lstMsg.BeginInvoke(new ShowMessageHandler(ShowMessageValue), new object[] { message }); 233 } 234 else 235 { 236 ShowMessageValue(message); 237 238 } 239 } 240 241 public void ShowMessageValue(string message) 242 { 243 if (lstMsg.Items.Count > 500) 244 { 245 lstMsg.Items.RemoveAt(0); 246 } 247 lstMsg.Items.Add(message); 248 lstMsg.SelectedIndex = lstMsg.Items.Count - 1; 249 } 250 251 private void button1_Click(object sender, EventArgs e) 252 { 253 //1. 判断listbox是否有选中的客户端 254 if (lstUser.SelectedItem != null) 255 { 256 //2.如果有选中的客户端,则根据键在_dict中找到对应客户端的Socket,然后向该客户端发送消息 257 Socket skClient = _dict[lstUser.SelectedItem.ToString()]; 258 259 Gloable.InstructCount = Gloable.InstructCount + 1; 260 261 byte[] sendHead = { 0x78, 0x78 }; 262 byte[] agreementId = { 0x80 };//协议号 263 byte[] serverSign = BitConverter.GetBytes(1);//服务器标志位 默认 264 Array.Reverse(serverSign); 265 byte[] instructContent = Encoding.ASCII.GetBytes(txtMsg.Text.Trim());//指令内容 266 267 byte[] instructLength = new byte[1] { (byte)Convert.ToInt32(serverSign.Length + instructContent.Length) };//指令长度 268 byte[] language = { 0x00, 0x01 }; 269 byte[] contentId = BitConverter.GetBytes((ushort)Gloable.InstructCount); 270 Array.Reverse(contentId); 271 byte[] errorCheck = { 0x00, 0x00 }; 272 byte sum = (byte)Convert.ToInt32(agreementId.Length + instructLength.Length + serverSign.Length + instructContent.Length + 273 language.Length + contentId.Length + errorCheck.Length); 274 byte[] packageLength = new byte[1] { sum }; 275 byte[] sendBody = Concat.ConcatBytes(packageLength, agreementId, instructLength, serverSign, instructContent, language, contentId, errorCheck); 276 UInt16 result = CRCCheck.GetCrc16(sendBody); 277 sendBody[sendBody.Length - 2] = (byte)((result >> 8) & 0xff); 278 sendBody[sendBody.Length - 1] = (byte)(result & 0xff); 279 280 byte[] sendTail = { 0x0D, 0x0A }; 281 byte[] allBytes2 = Concat.ConcatBytes(sendHead, sendBody, sendTail); 282 skClient.Send(allBytes2); 283 284 string msg = Concat.ToHexString2(allBytes2, allBytes2.Length); 285 string str = DateTime.Now.ToString("HH:mm:ss fff") + "--[" + skClient.RemoteEndPoint.ToString() + "]下发指令:" + txtMsg.Text.Trim(); 286 string content = DateTime.Now.ToString("HH:mm:ss fff") + "--[" + skClient.RemoteEndPoint.ToString() + "]下发指令:" + msg; 287 ShowMessage(str); 288 ShowMessage(content); 289 LogHelper.Instance.Info(str); 290 LogHelper.Instance.Info(content); 291 292 } 293 else 294 { 295 MessageBox.Show("请先选择一个客户端。"); 296 } 297 } 298 } 299 }
流程:调试助手是模拟web端下发指令。 web端下发指令给服务端,服务端和web端设定的协议进行解析,再根据和终端设备的协议 进行下发指令,终端接收后返回给服务端,再返回给web端
现在的问题是 第一次流程是没问题的,再下发指令,终端有反应,但是终端返回的数据服务端接收不到
服务端和终端一直可以互相接收发送,加入web端进来 就第一次可以接收发送,第二次就收不到终端返回数据了。请教一下是什么原因呢
代码太长看不懂。
web端-服务端-终端
1.请详细描述 web-服务端是长连接还是短连接,服务端-终端是长连接 还是短连接
2.服务端-终端,收发正常,“就第一次可以接收发送,第二次就收不到终端返回数据了”,是说的web端第二次就收不到返回的数据了?
试下
调用 skCommu.Close();并 using skCommu。
总之就是销毁skCommu。