首页 新闻 会员 周边 捐助

c# Socket 服务端第一次可以接收,第二次就接收不到

0
悬赏园豆:100 [待解决问题]

我现在有一个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 }
View Code

 


流程:调试助手是模拟web端下发指令。  web端下发指令给服务端,服务端和web端设定的协议进行解析,再根据和终端设备的协议 进行下发指令,终端接收后返回给服务端,再返回给web端

现在的问题是 第一次流程是没问题的,再下发指令,终端有反应,但是终端返回的数据服务端接收不到

 

服务端和终端一直可以互相接收发送,加入web端进来  就第一次可以接收发送,第二次就收不到终端返回数据了。请教一下是什么原因呢

清风依旧古少年的主页 清风依旧古少年 | 初学一级 | 园豆:8
提问于:2018-07-07 14:46
< >
分享
所有回答(2)
0

代码太长看不懂。

web端-服务端-终端

1.请详细描述 web-服务端是长连接还是短连接,服务端-终端是长连接 还是短连接

2.服务端-终端,收发正常,“就第一次可以接收发送,第二次就收不到终端返回数据了”,是说的web端第二次就收不到返回的数据了?

什麼江湖 | 园豆:116 (初学一级) | 2018-07-07 17:11
0

试下

 

调用 skCommu.Close();并 using skCommu。

总之就是销毁skCommu。

放逐人 | 园豆:694 (小虾三级) | 2018-07-10 11:56
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册