socket客户端与服务端正常通信,服务端过了一段时间就接收不到客户端的数据了
服务程序是接收数据的,然后大概1天左右都是正常的,突然一个时间点收不到数据了的问题解决
硬件与服务端通信,通过socket获取硬件数据,刚开始能够正常的接收数据,但是一段时间过后,服务端这边就无法接收到数据了,而且日志中也没有报错,暂时未知原因(因为是死循环,猜测是线程阻塞与等待),所以对服务端的Socket接收代码进行了优化后问题解决。
网上有各种骚操作,比如说,拔掉网线,重新启动,服务器可以恢复正常,有说关闭所有线程,手工启动,服务器能恢复正常,但这些都是治标不治本的办法,真正的原因还是因为线程阻塞了,当然每个场景不同,可能出现的问题不同,我这下面的解决主要就是针对线程阻塞导致,如有其他原因,可在 玩咖指针 首页添加我的微信给我发信息,一起探索交流。
以下是修改的关键代码:
以下是线程执行方法:
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);
}
}
}