socket客户端与服务端正常通信,服务端过了一段时间就接收不到客户端的数据了

服务程序是接收数据的,然后大概1天左右都是正常的,突然一个时间点收不到数据了的问题解决

     硬件与服务端通信,通过socket获取硬件数据,刚开始能够正常的接收数据,但是一段时间过后,服务端这边就无法接收到数据了,而且日志中也没有报错,暂时未知原因(因为是死循环,猜测是线程阻塞与等待),所以对服务端的Socket接收代码进行了优化后问题解决。


     网上有各种骚操作,比如说,拔掉网线,重新启动,服务器可以恢复正常,有说关闭所有线程,手工启动,服务器能恢复正常,但这些都是治标不治本的办法,真正的原因还是因为线程阻塞了,当然每个场景不同,可能出现的问题不同,我这下面的解决主要就是针对线程阻塞导致,如有其他原因,可在 玩咖指针 首页添加我的微信给我发信息,一起探索交流。


以下是修改的关键代码:

from clipboard




以下是线程执行方法:

        private void ClientReviceWorkThread(object obj)
        {
            int bytes;
            IDbContext db = DbList[0];
            byte[] reviceBytes = new byte[1024];
            string reviceContent = string.Empty;
            string reviceReturnJson = "\"return \":\"{0}\",\"id\":\"{1}\",\"res\":\"{2}\"";

            while (true)
            {
                SocketThread socketThread = obj as SocketThread;
                Socket socketClient = socketThread.socket;
                Thread.Sleep(100);
                string guid = Guid.NewGuid().ToString("N");

                try
                {
                    if (App.ServerLogIsWrite)
                        DataOperation.WriteSys_ServerReivceLog(db, "接收模块", guid, socketThread.guid, "开始任务");

                    //接收请求如果已经断开连接了,就退出当前循环
                    if (!socketClient.Connected)
                    {
                        this.TryAction(() =>
                        {
                            socketThread.socket.Close(); //关闭客户端Socket,清理资源
                            socketThread.status = SocketThreadStatus.NoConnectionWaitStop;
                        }, (ex1) => { });
                        break;
                    }

                    //数据请求预处理
                    bool isNormal = false;
                    bool isException = false;
                    this.TryAction(() =>
                    {
                        if (socketClient.Available <= 0)
                            isNormal = false;
                        else
                            isNormal = true;
                    }, (ex) => { isException = true; });

                    //连接已关闭,退出循环
                    if (isException)
                    {
                        this.TryAction(() =>
                        {
                            socketThread.socket.Close(); //关闭客户端Socket,清理资源
                            socketThread.status = SocketThreadStatus.NoAvailableWaitStop;
                        }, (ex1) => { });
                        break;
                    }
                    //如果没有数据可以接收,跳出当前循环
                    if (!isNormal)
                        continue;

                    if (App.ServerLogIsWrite)
                        DataOperation.WriteSys_ServerReivceLog(db, "接收模块", guid, socketThread.guid, "接收数据开始");

                    socketClient.ReceiveTimeout = 1000 * 10;
                    do
                    {
                        bytes = socketClient.Receive(reviceBytes, reviceBytes.Length, 0); //从客户端接受消息
                        reviceContent = Encoding.Default.GetString(reviceBytes, 0, bytes);
                    }
                    while (bytes == 1024);

                    if (App.ServerLogIsWrite)
                        DataOperation.WriteSys_ServerReivceLog(db, "接收模块", guid, socketThread.guid, "接收数据结束");

                    VoidResult result = null;
                    if (reviceContent.IsEmptys())
                    {
                        result = SocketHelper.SendDataToDeviceRevice(socketClient, "数据接收中断");
                        continue;
                    }

                    ReviceJson revice = JsonHelper.TryJsonToObject<ReviceJson>(reviceContent);
                    if (revice == null)
                    {
                        result = SocketHelper.SendDataToDeviceRevice(socketClient, "指令错误");
                        continue;
                    }

                    string remoteEndPoint = socketClient.RemoteEndPoint.ToString();
                    string key = remoteEndPoint + "_DevID_" + revice.id;

                    //数据接收成功,开始执行开始函数
                    if (ProcessWorkBegin != null && socketClient.Connected)
                        this.ProcessWorkBegin(null, key + ":" + reviceContent);

                    //一个设备只能有一个连接,有多个时,需要断开之前或者不允许这个连接
                    string currConnectionKey = string.Empty;
                    DateTime clientLastReviceHeartbeatTime = DateTime.Now;
                    ClientInfo client = null;

                    foreach (var connectKey in ReviceConnectClientArrayObject.Keys)
                    {
                        if (connectKey == key)
                        {
                            continue;
                        }
                        if (connectKey.Contains("_DevID_" + revice.id))
                        {
                            currConnectionKey = connectKey;
                            break;
                        }
                        if (connectKey.Contains(remoteEndPoint))
                        {
                            ReviceConnectClientArrayObject.TryGetValue(connectKey, out client);
                            break;
                        }
                    }
                    //如果当前连接已经绑定了设备,无法再绑定其他设备
                    if (client != null)
                    {
                        result = SocketHelper.SendDataToDeviceRevice(socketClient, "已经绑定设备,其他设备的指令无法解析");
                        continue;
                    }

                    //如果已经有其他连接在使用设备,需移除已经连接的设备
                    if (!currConnectionKey.IsEmptys() && ReviceConnectClientArrayObject.TryGetValue(currConnectionKey, out client))
                    {
                        this.TryAction(() =>
                        {
                            clientLastReviceHeartbeatTime = client.LastReviceHeartbeatTime;
                            //移除前,先设定设备为离线状态
                            if (client.State == true)
                            {
                                client.State = false;
                                DataOperation.UpdateDeviceOnlineStatusByDeviceCode(db, client.ReviceDeviceCode, false);
                            }

                            this.TryAction(() =>
                            {
                                client.ClientSocket.Shutdown(SocketShutdown.Both);
                                Thread.Sleep(10);
                                client.ClientSocket.Close();
                            }, (ex) => { });

                            ReviceConnectClientArrayObject.TryRemove(currConnectionKey, out client);
                        }, (ex) => { });
                    }

                    //如果请求连接不存在
                    if (!ReviceConnectClientArrayObject.ContainsKey(key))
                    {
                        client = new ClientInfo() { ClientID = key, RemoteEndPoint = remoteEndPoint, ReviceDeviceCode = revice.id };
                        client.ClientSocket = socketClient;
                        client.State = true;
                        //新连接设置当前时间为心跳检测的最新时间
                        client.LastReviceHeartbeatTime = clientLastReviceHeartbeatTime;
                        this.ReviceConnectClientArrayObject.TryAdd(key, client);
                    }
                    else
                    {
                        //连接存在,并且连接是心跳包,更新当前时间为心跳检测的最新时间
                        if (ReviceConnectClientArrayObject.TryGetValue(key, out client) && revice.fun == "alive")
                        {
                            client.LastReviceHeartbeatTime = clientLastReviceHeartbeatTime;
                        }
                    }

                    //返回给客户端信息
                    string msg = string.Format(reviceReturnJson, revice.fun, revice.id, "ok");
                    msg = "{" + msg + "}";
                    SocketHelper.SendDataToDeviceRevice(socketClient, msg);

                    //不用队列处理
                    T_DeviceModel device = DataOperation.GetDeviceByReviceDeviceCode(db, GetAreaList(), revice.id);
                    if (device != null)
                    {
                        WriteReviceInfoReal(dbMain, device, revice);
                    }

                    //数据接收完毕,开始执行结束函数
                    if (ProcessWorkEnd != null && socketClient.Connected)
                        this.ProcessWorkEnd(socketClient, "数据已接收");
                }
                catch (Exception ex)
                {
                    DataOperation.WriteSys_ServerLog(db, "接收模块", ex);
                }
            }
        }    



玩咖指针 2020-04-08 09:06:54