|
@@ -1,6 +1,7 @@
|
|
using System;
|
|
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Generic;
|
|
|
|
+using System.ComponentModel;
|
|
using System.Linq;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Net.Sockets;
|
|
@@ -10,34 +11,18 @@ using System.Threading.Tasks;
|
|
|
|
|
|
namespace DWZB_Agv_Agreement
|
|
namespace DWZB_Agv_Agreement
|
|
{
|
|
{
|
|
-
|
|
|
|
- #region 定义委托、事件
|
|
|
|
- /// <summary>
|
|
|
|
- /// 获取消息委托
|
|
|
|
- /// </summary>
|
|
|
|
- /// <param name="sender">消息主体buffer</param>
|
|
|
|
- /// <param name="ip">ip</param>
|
|
|
|
- /// <param name="dataLength">数据长度</param>
|
|
|
|
- /// <param name="e">事件类对象</param>
|
|
|
|
- public delegate void GetMessageEventHandler(object sender, string ip, int dataLength, EventArgs e);
|
|
|
|
- /// <summary>
|
|
|
|
- /// 获取链接委托
|
|
|
|
- /// </summary>
|
|
|
|
- /// <param name="sender">链接进入的IP</param>
|
|
|
|
- /// <param name="e">事件类对象</param>
|
|
|
|
- public delegate void GetAcceptEventHandler(object sender, EventArgs e);
|
|
|
|
- /// <summary>
|
|
|
|
- /// 关闭链接委托
|
|
|
|
- /// </summary>
|
|
|
|
- /// <param name="sender">链接进入的IP</param>
|
|
|
|
- /// <param name="e">事件类对象</param>
|
|
|
|
- public delegate void GetCloseEventHandler(object sender, EventArgs e);
|
|
|
|
- #endregion
|
|
|
|
-
|
|
|
|
public class SocketServerHelper
|
|
public class SocketServerHelper
|
|
{
|
|
{
|
|
|
|
|
|
- #region 事件
|
|
|
|
|
|
+ #region 自定义事件
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 获取消息委托
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="sender">消息主体buffer</param>
|
|
|
|
+ /// <param name="ip">ip</param>
|
|
|
|
+ /// <param name="dataLength">数据长度</param>
|
|
|
|
+ /// <param name="e">事件类对象</param>
|
|
|
|
+ public delegate void GetMessageEventHandler(object sender, string ip, int dataLength, EventArgs e);
|
|
public event GetMessageEventHandler MessageEvent;
|
|
public event GetMessageEventHandler MessageEvent;
|
|
/// <summary>
|
|
/// <summary>
|
|
/// 触发接收到Socket客户端消息的委托事件
|
|
/// 触发接收到Socket客户端消息的委托事件
|
|
@@ -51,6 +36,13 @@ namespace DWZB_Agv_Agreement
|
|
MessageEvent?.Invoke(sender, ip, dataLength, e);
|
|
MessageEvent?.Invoke(sender, ip, dataLength, e);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 获取链接委托
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="sender">链接进入的IP</param>
|
|
|
|
+ /// <param name="e">事件类对象</param>
|
|
|
|
+ public delegate void GetAcceptEventHandler(object sender, EventArgs e);
|
|
public event GetAcceptEventHandler AcceptEvent;
|
|
public event GetAcceptEventHandler AcceptEvent;
|
|
/// <summary>
|
|
/// <summary>
|
|
/// 触发Socket客户接入服务端的委托事件
|
|
/// 触发Socket客户接入服务端的委托事件
|
|
@@ -62,6 +54,12 @@ namespace DWZB_Agv_Agreement
|
|
AcceptEvent?.Invoke(sender, e);
|
|
AcceptEvent?.Invoke(sender, e);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 关闭链接委托
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="sender">链接进入的IP</param>
|
|
|
|
+ /// <param name="e">事件类对象</param>
|
|
|
|
+ public delegate void GetCloseEventHandler(object sender, EventArgs e);
|
|
public event GetCloseEventHandler CloseEvent;
|
|
public event GetCloseEventHandler CloseEvent;
|
|
/// <summary>
|
|
/// <summary>
|
|
/// 触发关闭链接委托事件
|
|
/// 触发关闭链接委托事件
|
|
@@ -81,17 +79,17 @@ namespace DWZB_Agv_Agreement
|
|
/// </summary>
|
|
/// </summary>
|
|
public Socket SocketServerListen;
|
|
public Socket SocketServerListen;
|
|
/// <summary>
|
|
/// <summary>
|
|
|
|
+ /// Socket服务端监控可取消线程对象
|
|
|
|
+ /// </summary>
|
|
|
|
+ public BackgroundWorker SocketServerThWorker;
|
|
|
|
+ /// <summary>
|
|
/// Socket客户端套接字对象字典
|
|
/// Socket客户端套接字对象字典
|
|
/// </summary>
|
|
/// </summary>
|
|
public ConcurrentDictionary<string, Socket> dicSockClientList = new ConcurrentDictionary<string, Socket>();
|
|
public ConcurrentDictionary<string, Socket> dicSockClientList = new ConcurrentDictionary<string, Socket>();
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Socket客户端接收数据线程字典
|
|
/// Socket客户端接收数据线程字典
|
|
/// </summary>
|
|
/// </summary>
|
|
- //public ConcurrentDictionary<string, Thread> dicSockThreadList = new ConcurrentDictionary<string, Thread>();
|
|
|
|
- /// <summary>
|
|
|
|
- /// 监听客户端连接的线程标识
|
|
|
|
- /// </summary>
|
|
|
|
- private bool Flag_Listen = false;
|
|
|
|
|
|
+ public ConcurrentDictionary<string, BackgroundWorker> dicSockThreadWorkerList = new ConcurrentDictionary<string, BackgroundWorker>();
|
|
#endregion
|
|
#endregion
|
|
|
|
|
|
#region 方法
|
|
#region 方法
|
|
@@ -116,7 +114,6 @@ namespace DWZB_Agv_Agreement
|
|
//设置监听队列
|
|
//设置监听队列
|
|
SocketServerListen.Listen(100);
|
|
SocketServerListen.Listen(100);
|
|
LogHelper.WriteLog($"Socket服务端 ip地址:【{ip}】端口号:【{port}】 开启监听成功!", LogTypeEnum.SocketRun);
|
|
LogHelper.WriteLog($"Socket服务端 ip地址:【{ip}】端口号:【{port}】 开启监听成功!", LogTypeEnum.SocketRun);
|
|
- Flag_Listen = true;
|
|
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
catch (Exception ex)
|
|
{
|
|
{
|
|
@@ -176,12 +173,94 @@ namespace DWZB_Agv_Agreement
|
|
//}
|
|
//}
|
|
#endregion
|
|
#endregion
|
|
|
|
|
|
|
|
+ public void StartListenClientAccept()
|
|
|
|
+ {
|
|
|
|
+ SocketServerThWorker = new BackgroundWorker
|
|
|
|
+ {
|
|
|
|
+ WorkerReportsProgress = true,
|
|
|
|
+ WorkerSupportsCancellation = true
|
|
|
|
+ };
|
|
|
|
+ SocketServerThWorker.DoWork += (object sender, DoWorkEventArgs e) => {
|
|
|
|
+ while (true)
|
|
|
|
+ {
|
|
|
|
+ if (SocketServerThWorker.CancellationPending)
|
|
|
|
+ {
|
|
|
|
+ e.Cancel = true;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ try
|
|
|
|
+ {
|
|
|
|
+ Socket newSoket = SocketServerListen.Accept();
|
|
|
|
+ string ipAddress = newSoket.RemoteEndPoint.ToString();
|
|
|
|
+ BackgroundWorker ThWorkerMd = new BackgroundWorker
|
|
|
|
+ {
|
|
|
|
+ WorkerReportsProgress = true,
|
|
|
|
+ WorkerSupportsCancellation = true
|
|
|
|
+ };
|
|
|
|
+ ThWorkerMd.DoWork += (object sender, DoWorkEventArgs e) => {
|
|
|
|
+ Socket newSocket = e.Argument as Socket;//转成对应的Socket类型
|
|
|
|
+ string IPPortID = newSocket.RemoteEndPoint.ToString();//这个线程ID
|
|
|
|
+ while (true)
|
|
|
|
+ {
|
|
|
|
+ if (ThWorkerMd.CancellationPending)
|
|
|
|
+ {
|
|
|
|
+ e.Cancel = true;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ byte[] buffer = new byte[1024 * 2];
|
|
|
|
+ int receiveLength;
|
|
|
|
+ try //由于Socket中的Receive方法容易抛出异常,所以我们在这里要捕获异常。
|
|
|
|
+ {
|
|
|
|
+ bool a = dicSockClientList[IPPortID].Poll(10, SelectMode.SelectRead);
|
|
|
|
+ receiveLength = dicSockClientList[IPPortID].Receive(buffer);//接收从客户端发送过来的数据
|
|
|
|
+ if (a)
|
|
|
|
+ {
|
|
|
|
+ LogHelper.WriteLog($"Socket客户端:【{IPPortID}】主动断开连接,Socket服务端准备移除该客户端连接!", LogTypeEnum.SocketErr);
|
|
|
|
+ //触发Socket客户端断开连接实践
|
|
|
|
+ OnCloseEvent(IPPortID, EventArgs.Empty);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ catch (Exception ex)
|
|
|
|
+ {
|
|
|
|
+ LogHelper.WriteLog($"Socket客户端:【{IPPortID}】数据接受发生异常:【{ex.Message}】,Socket服务端已经移除该客户端连接!", LogTypeEnum.SocketErr);
|
|
|
|
+ //触发Socket客户端断开连接实践
|
|
|
|
+ OnCloseEvent(IPPortID, EventArgs.Empty);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ if (receiveLength > 0)
|
|
|
|
+ {
|
|
|
|
+ //记录接收到的原始数据
|
|
|
|
+ LogHelper.WriteLog($"Socket客户端:【{IPPortID}】接收到:【{receiveLength}】字节数据,数据内容:【{BitConverter.ToString(buffer, 0, receiveLength)}】。", LogTypeEnum.SocketData);
|
|
|
|
+ //触发接收到Socket客户端发送数据的事件
|
|
|
|
+ OnNewMessage(buffer, IPPortID, receiveLength, EventArgs.Empty);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ ThWorkerMd.RunWorkerAsync(newSoket);
|
|
|
|
+
|
|
|
|
+ dicSockClientList.TryAdd(ipAddress, newSoket);
|
|
|
|
+ dicSockThreadWorkerList.TryAdd(ipAddress, ThWorkerMd);
|
|
|
|
+ //触发Socket客户端接入服务端事件
|
|
|
|
+ OnAcceptEvent(ipAddress, EventArgs.Empty);
|
|
|
|
+
|
|
|
|
+ LogHelper.WriteLog($"Socket客户端:【{ipAddress}】连接成功!", LogTypeEnum.SocketRun);
|
|
|
|
+ }
|
|
|
|
+ catch (Exception ex)
|
|
|
|
+ {
|
|
|
|
+ LogHelper.WriteLog($"Socket服务端监听客户端的连接的函数发生异常:【{ex.Message}】", LogTypeEnum.SocketErr);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ SocketServerThWorker.RunWorkerAsync();
|
|
|
|
+ }
|
|
|
|
+
|
|
/// <summary>
|
|
/// <summary>
|
|
/// 循环监听客户端的连接
|
|
/// 循环监听客户端的连接
|
|
/// </summary>
|
|
/// </summary>
|
|
public void ListeneSocketClientConnectAccept()
|
|
public void ListeneSocketClientConnectAccept()
|
|
{
|
|
{
|
|
- while (Flag_Listen)
|
|
|
|
|
|
+ while (true)
|
|
{
|
|
{
|
|
try
|
|
try
|
|
{
|
|
{
|
|
@@ -218,7 +297,7 @@ namespace DWZB_Agv_Agreement
|
|
Socket newSocket = socket as Socket;//转成对应的Socket类型
|
|
Socket newSocket = socket as Socket;//转成对应的Socket类型
|
|
string IPPortID = newSocket.RemoteEndPoint.ToString();//这个线程ID
|
|
string IPPortID = newSocket.RemoteEndPoint.ToString();//这个线程ID
|
|
|
|
|
|
- while (Flag_Listen)
|
|
|
|
|
|
+ while (true)
|
|
{
|
|
{
|
|
byte[] buffer = new byte[1024 * 2];
|
|
byte[] buffer = new byte[1024 * 2];
|
|
int receiveLength;
|
|
int receiveLength;
|
|
@@ -256,21 +335,40 @@ namespace DWZB_Agv_Agreement
|
|
/// </summary>
|
|
/// </summary>
|
|
public void CloseServer()
|
|
public void CloseServer()
|
|
{
|
|
{
|
|
|
|
+ if (SocketServerThWorker.IsBusy)
|
|
|
|
+ {
|
|
|
|
+ SocketServerThWorker.CancelAsync();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ lock (dicSockThreadWorkerList)
|
|
|
|
+ {
|
|
|
|
+ foreach (var item in dicSockThreadWorkerList)
|
|
|
|
+ {
|
|
|
|
+ if (item.Value.IsBusy)
|
|
|
|
+ {
|
|
|
|
+ item.Value.CancelAsync();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ dicSockThreadWorkerList.Clear();//清除字典
|
|
|
|
+ }
|
|
|
|
+
|
|
lock (dicSockClientList)
|
|
lock (dicSockClientList)
|
|
{
|
|
{
|
|
foreach (var item in dicSockClientList)
|
|
foreach (var item in dicSockClientList)
|
|
{
|
|
{
|
|
|
|
+ item.Value.Disconnect(true);
|
|
item.Value.Close();//关闭每一个连接
|
|
item.Value.Close();//关闭每一个连接
|
|
}
|
|
}
|
|
dicSockClientList.Clear();//清除字典
|
|
dicSockClientList.Clear();//清除字典
|
|
}
|
|
}
|
|
- Flag_Listen = false;
|
|
|
|
- //服务端不能主动关闭连接,需要把监听到的连接逐个关闭
|
|
|
|
- SocketServerListen.Shutdown(SocketShutdown.Both);
|
|
|
|
|
|
+
|
|
if (SocketServerListen != null)
|
|
if (SocketServerListen != null)
|
|
{
|
|
{
|
|
SocketServerListen.Close();
|
|
SocketServerListen.Close();
|
|
|
|
+ SocketServerListen.Dispose();
|
|
|
|
+ //SocketServerListen = null;
|
|
}
|
|
}
|
|
|
|
+ SocketServerThWorker.Dispose();
|
|
}
|
|
}
|
|
|
|
|
|
public void SendData(string ipAddress,byte[] btArr)
|
|
public void SendData(string ipAddress,byte[] btArr)
|
|
@@ -280,7 +378,11 @@ namespace DWZB_Agv_Agreement
|
|
|
|
|
|
public void RemoveSocketClient(string ipAddress)
|
|
public void RemoveSocketClient(string ipAddress)
|
|
{
|
|
{
|
|
|
|
+ dicSockClientList[ipAddress].Disconnect(true);
|
|
|
|
+ dicSockClientList[ipAddress].Close();//关闭每一个连接
|
|
dicSockClientList.TryRemove(ipAddress, out _);
|
|
dicSockClientList.TryRemove(ipAddress, out _);
|
|
|
|
+ dicSockThreadWorkerList[ipAddress].CancelAsync();
|
|
|
|
+ dicSockThreadWorkerList.TryRemove(ipAddress, out _);
|
|
}
|
|
}
|
|
#endregion
|
|
#endregion
|
|
|
|
|