背景
工控上位机系统开发过程中不可避免的会用到socket通信技术,但是在支持多客户端并发连接时,常规方法效率很低。提高通信效率的一种途径就是使用Socket的异步通信,最开始从网上查了些资料,并进行整理。如果服务端使用异步通信,客户端使用常规同步通信(SocketTool.exe进行测试),没有什么问题。这个测试版本大概是在7年前写的,而且放到现场已经用了很多年。最近把Socket客户端也改为了异步通信,却发现最初写的服务端代码还是有问题。今天反复测试,最终修复bug。现把最新整理的完整通讯类库源码共享给大家。
关键代码
因为类库依赖了插件库ICSharp.Core.dll,请把代码中进行日志输出的部分,改为Console.WriteLine()输出,
实际把ICSharpCode.Core.LoggingService.Error换成Console.WriteLine
TcpService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Configuration;
using System.Net.Sockets;
namespace Mesnac.Communication
{
public class TcpService
{
private static TcpService instance = null;
private SocketListener listener = null;
private int maxConnection = 100; //允许的最大连接数
private int bufferSize = 1024 * 1024; //接收缓冲区的大小
private int port = 3666; //监听的端口号
//private string ip = "127.0.0.1"; //监听的IP地址
private TcpService()
{
try
{
object oMaxConnection = ConfigurationManager.AppSettings["MaxConnection"];
if (oMaxConnection != null)
{
int.TryParse(oMaxConnection.ToString(), out this.maxConnection);
}
object oPort = ConfigurationManager.AppSettings["Port"];
if (oPort != null)
{
int.TryParse(oPort.ToString(), out this.port);
}
ICSharpCode.Core.LoggingService<TcpService>.Debug("最大连接数:" + this.maxConnection);
ICSharpCode.Core.LoggingService<TcpService>.Debug("侦听的端口号:" + this.port);
this.listener = new SocketListener(this.maxConnection, this.bufferSize, this.GetIDByIP);
this.listener.StartListenThread += new SocketListener.StartListenHandler(listener_StartListenThread);
this.listener.ProcessAcceptComplete += new EventHandler<SocketAsyncEventArgs>(listener_ProcessAcceptComplete);
this.listener.OnSended += new SocketListener.SendCompletedHandler(listener_OnSended);
this.listener.OnMsgReceived += new SocketListener.ReceiveMsgHandler(listener_OnMsgReceived);
this.listener.OnClientClose += new SocketListener.ClientClose(listener_OnClientClose);
this.listener.Init();
try
{
this.listener.Start(this.port);
}
catch(System.Net.Sockets.SocketException se)
{
if (se.SocketErrorCode == System.Net.Sockets.SocketError.AddressAlreadyInUse)
{
ICSharpCode.Core.LoggingService<TcpService>.Error(String.Format("端口号{0}已被占用!", this.port));
}
}
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<TcpService>.Error(ex.Message);
ICSharpCode.Core.LoggingService<TcpService>.Error(ex.StackTrace);
}
}
/// <summary>
/// 处理客户端连接完成事件
/// </summary>
/// <param name="sender">客户端ip</param>
/// <param name="e"></param>
private void listener_ProcessAcceptComplete(object sender, SocketAsyncEventArgs e)
{
//触发处理客户端连接完成事件
if (this.ProcessAcceptComplete != null)
{
this.ProcessAcceptComplete(sender, e);
}
}
private void listener_OnMsgReceived(string uid, string info)
{
if (this.ReceiveMsgHandler != null)
{
this.ReceiveMsgHandler(uid, info);
}
ICSharpCode.Core.LoggingService<TcpService>.Debug(String.Format("接收到{0}发送的消息:{1}", uid, info));
}
private void listener_OnSended(string uid, string exception)
{
if (exception == "100")
{
ICSharpCode.Core.LoggingService<TcpService>.Debug(String.Format("已发送消息到{0}", uid));
}
else
{
//ICSharpCode.Core.LoggingService.Error(String.Format("消息发送错误:{0}", exception));
ICSharpCode.Core.LoggingService<TcpService>.Warn("消息发送错误:客户端已经断开连接!");
}
}
/// <summary>
/// 客户端断开连接的事件处理程序
/// </summary>
/// <param name="uid"></param>
private void listener_OnClientClose(string uid)
{
ICSharpCode.Core.LoggingService<TcpService>.Debug(String.Format("{0}:断开了连接...{1:yyyy-MM-dd HH:mm:ss}", uid, DateTime.Now));
}
private void listener_StartListenThread()
{
ICSharpCode.Core.LoggingService<TcpService>.Debug("开始侦听...");
ThreadPool.QueueUserWorkItem(new WaitCallback(this.StartListenCallBack), true);
}
private void StartListenCallBack(object listenFlag)
{
this.listener.ListenFlag = Convert.ToBoolean(listenFlag);
this.listener.Listen();
}
/// <summary>
/// 获取侦听的服务器IP地址
/// </summary>
/// <param name="ip"></param>
/// <returns></returns>
private string GetIDByIP(string ip)
{
return ip;
}
/// <summary>
/// TCP通信服务实例
/// </summary>
public static TcpService Instance
{
get
{
if (instance == null)
{
instance = new TcpService();
}
return instance;
}
}
/// <summary>
/// 启动服务
/// </summary>
public static void StartService()
{
if (instance == null)
{
instance = new TcpService();
}
}
/// <summary>
/// 重启服务
/// </summary>
public static void ReStartService()
{
StopService();
StartService();
}
/// <summary>
/// 停止服务
/// </summary>
public static void StopService()
{
if (instance != null)
{
try
{
instance.listener.Stop();
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<TcpService>.Error("停止Socket侦听失败:" + ex.Message);
}
finally
{
instance = null;
}
}
}
/// <summary>
/// 发送消息至所有连接至本服务器的客户端计算机
/// </summary>
/// <param name="msg">消息内容</param>
public void NetSendMsg(string msg)
{
foreach (string uid in this.listener.OnlineUID)
{
this.listener.Send(uid, msg);
}
}
/// <summary>
/// 发送消息至指定计算机
/// </summary>
/// <param name="uid">计算机IP地址</param>
/// <param name="msg">消息内容</param>
public void NetSendMsg(string uid, string msg)
{
this.listener.Send(uid, msg);
}
/// <summary>
/// 接收到信息时触发的事件
/// </summary>
public event SocketListener.ReceiveMsgHandler ReceiveMsgHandler;
/// <summary>
/// 处理接收客户端连接完成事件
/// </summary>
public event EventHandler<SocketAsyncEventArgs> ProcessAcceptComplete;
}
}
SocketListener.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Configuration;
namespace Mesnac.Communication
{
public sealed class SocketListener : IDisposable
{
/// <summary>
/// 缓冲区
/// </summary>
private BufferManager bufferManager;
/// <summary>
/// 服务器端Socket
/// </summary>
private Socket listenSocket;
/// <summary>
/// 服务同步锁
/// </summary>
private Mutex mutex;
/// <summary>
/// 当前连接数
/// </summary>
private Int32 numConnections;
/// <summary>
/// 最大并发量
/// </summary>
private Int32 numConcurrence;
/// <summary>
/// 服务器状态
/// </summary>
private ServerState serverstate;
/// <summary>
/// 读取写入字节
/// </summary>
private const Int32 opsToPreAlloc = 1;
/// <summary>
/// Socket连接池
/// </summary>
private SocketAsyncEventArgsPool readWritePool;
/// <summary>
/// 并发控制信号量
/// </summary>
private Semaphore semaphoreAcceptedClients;
/// <summary>
/// 通信协议
/// </summary>
private RequestHandler handler;
/// <summary>
/// 回调委托
/// </summary>
/// <param name="IP"></param>
/// <returns></returns>
public delegate string GetIDByIPFun(string IP);
/// <summary>
/// 回调方法实例
/// </summary>
private GetIDByIPFun GetIDByIP;
/// <summary>
/// 接收到信息时的事件委托
/// </summary>
/// <param name="info"></param>
public delegate void ReceiveMsgHandler(string uid, string info);
/// <summary>
/// 接收到信息时的事件
/// </summary>
public event ReceiveMsgHandler OnMsgReceived;
/// <summary>
/// 客户端关闭连接时的委托
/// </summary>
/// <param name="uid"></param>
public delegate void ClientClose(string uid);
/// <summary>
/// 客户端关闭连接时的事件
/// </summary>
public event ClientClose OnClientClose;
/// <summary>
/// 开始监听数据的委托
/// </summary>
public delegate void StartListenHandler();
/// <summary>
/// 开始监听数据的事件
/// </summary>
public event StartListenHandler StartListenThread;
/// <summary>
/// 发送信息完成后的委托
/// </summary>
/// <param name="successorfalse"></param>
public delegate void SendCompletedHandler(string uid, string exception);
/// <summary>
/// 发送信息完成后的事件
/// </summary>
public event SendCompletedHandler OnSended;
private bool listenFlag = false;
public bool ListenFlag { get { return this.listenFlag; } set { this.listenFlag= value; } }
/// <summary>
/// 获取当前的并发数
/// </summary>
public Int32 NumConnections
{
get { return this.numConnections; }
}
/// <summary>
/// 最大并发数
/// </summary>
public Int32 MaxConcurrence
{
get { return this.numConcurrence; }
}
/// <summary>
/// 返回服务器状态
/// </summary>
public ServerState State
{
get
{
return serverstate;
}
}
/// <summary>
/// 获取当前在线用户的UID
/// </summary>
public string[] OnlineUID
{
get { return readWritePool.OnlineUID; }
}
/// <summary>
/// 初始化服务器端
/// </summary>
/// <param name="numConcurrence">并发的连接数量(1000以上)</param>
/// <param name="receiveBufferSize">每一个收发缓冲区的大小(32768)</param>
public SocketListener(Int32 numConcurrence, Int32 receiveBufferSize, GetIDByIPFun GetIDByIP)
{
try
{
this.mutex = new Mutex();
serverstate = ServerState.Initialing;
this.numConnections = 0;
this.numConcurrence = numConcurrence;
this.bufferManager = new BufferManager(receiveBufferSize * numConcurrence * opsToPreAlloc, receiveBufferSize);
this.readWritePool = new SocketAsyncEventArgsPool(numConcurrence);
this.semaphoreAcceptedClients = new Semaphore(numConcurrence, numConcurrence);
handler = new RequestHandler();
this.GetIDByIP = GetIDByIP;
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketListener>.Error("SocketListener错误:" + ex.Message, ex);
ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
}
}
/// <summary>
/// 服务端初始化
/// </summary>
public void Init()
{
try
{
this.bufferManager.InitBuffer();
SocketAsyncEventArgsWithId readWriteEventArgWithId;
for (Int32 i = 0; i < this.numConcurrence; i++)
{
readWriteEventArgWithId = new SocketAsyncEventArgsWithId();
readWriteEventArgWithId.SendSAEA.Completed += new EventHandler<SocketAsyncEventArgs>(OnSendCompleted);
readWriteEventArgWithId.ReceiveSAEA.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceiveCompleted);
//只给接收的SocketAsyncEventArgs设置缓冲区
this.bufferManager.SetBuffer(readWriteEventArgWithId.ReceiveSAEA);
this.readWritePool.Push(readWriteEventArgWithId);
}
serverstate = ServerState.Inited;
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketListener>.Error("ScoketListner Init错误:" + ex.Message, ex);
ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
}
}
/// <summary>
/// 启动服务器
/// </summary>
/// <param name="data">端口号</param>
public void Start(Object data)
{
try
{
Int32 port = (Int32)data;
IPAddress[] addresslist = Dns.GetHostEntry(Environment.MachineName).AddressList;
IPAddress ipAddress = addresslist[addresslist.Length - 1];
object listenServerIP = ConfigurationManager.AppSettings["ListenServerIP"];
if (listenServerIP != null)
{
IPAddress.TryParse(listenServerIP.ToString(), out ipAddress);
}
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);
this.listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
{
this.listenSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
this.listenSocket.Bind(new IPEndPoint(IPAddress.IPv6Any, localEndPoint.Port));
}
else
{
this.listenSocket.Bind(localEndPoint);
}
this.listenSocket.Listen(100);
this.StartAccept(null);
//开始监听已连接用户的发送数据
if (StartListenThread != null)
{
StartListenThread();
}
serverstate = ServerState.Running;
mutex.WaitOne();
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketListener>.Error("SocketListner Start错误:" + ex.Message, ex);
ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
}
}
/// <summary>
/// 开始监听线程的入口函数
/// </summary>
public void Listen()
{
while (this.listenFlag)
{
lock (readWritePool)
{
string currUser = String.Empty;
try
{
string[] keys = readWritePool.OnlineUID;
foreach (string uid in keys)
{
currUser = uid;
if (uid != null && readWritePool.BusyPool.ContainsKey(uid) && readWritePool.BusyPool[uid] != null)
{
SocketAsyncEventArgsWithId sawd = readWritePool.BusyPool[uid];
if (sawd != null || sawd.ReceiveSAEA == null)
{
if (readWritePool.BusyPool[uid].ReceiveSAEA.UID == null)
{
readWritePool.BusyPool[uid].ReceiveSAEA.UID = uid;
}
if ((readWritePool.BusyPool[uid].ReceiveSAEA.UserToken as Socket).Available > 0)// readWritePool.BusyPool[uid].ReceiveSAEA.LastOperation != SocketAsyncOperation.Receive)
{
Boolean willRaiseEvent = (readWritePool.BusyPool[uid].ReceiveSAEA.UserToken as Socket).ReceiveAsync(readWritePool.BusyPool[uid].ReceiveSAEA);
if (!willRaiseEvent)
ProcessReceive(readWritePool.BusyPool[uid].ReceiveSAEA);
}
}
else
{
readWritePool.BusyPool.Remove(uid);
}
#region 注释
//else if (readWritePool.BusyPool[uid].ReceiveSAEA.LastOperation == SocketAsyncOperation.None)
//{
// //以下为心跳处理
// Boolean willRaiseEvent = (readWritePool.BusyPool[uid].ReceiveSAEA.UserToken as Socket).ReceiveAsync(readWritePool.BusyPool[uid].ReceiveSAEA);
//}
//else if (readWritePool.BusyPool[uid].ReceiveSAEA.LastOperation == SocketAsyncOperation.Receive && readWritePool.BusyPool[uid].ReceiveSAEA.SocketError == SocketError.Success)
//{
// try
// {
// try
// {
// lock (String.Empty)
// {
// if (readWritePool.BusyPool[uid].IsAllowReceive)
// {
// //以下为心跳处理
// Boolean willRaiseEvent = (readWritePool.BusyPool[uid].ReceiveSAEA.UserToken as Socket).ReceiveAsync(readWritePool.BusyPool[uid].ReceiveSAEA);
// }
// }
// }
// catch (System.InvalidOperationException ex)
// {
// //ICSharpCode.Core.LoggingService.Error("心跳处理报错无效操作:" + ex.Message);
// //如果产生无效操作异常,说明正常连接,正在接收数据,停止心跳包发送数据
// if (readWritePool.BusyPool.ContainsKey(uid))
// {
// readWritePool.BusyPool[uid].IsAllowReceive = false;
// }
// }
// }
// catch (Exception ex)
// {
// ICSharpCode.Core.LoggingService.Error("心跳处理报错:" + ex.Message);
// ICSharpCode.Core.LoggingService.Error(ex.StackTrace);
// if (readWritePool.BusyPool.ContainsKey(uid))
// {
// readWritePool.BusyPool[uid].IsAllowReceive = false;
// }
// }
//}
#endregion
}
}
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketListener>.Error("监听错误:" + ex.Message, ex);
//ICSharpCode.Core.LoggingService.Error(ex.StackTrace);
try
{
if (readWritePool.BusyPool.ContainsKey(currUser) && readWritePool.BusyPool[currUser] != null)
{
readWritePool.BusyPool[currUser].Dispose();
readWritePool.BusyPool.Remove(currUser);
}
else
{
readWritePool.BusyPool.Remove(currUser);
}
Interlocked.Decrement(ref this.numConnections);
ICSharpCode.Core.LoggingService<SocketListener>.Debug("当前连接数:" + this.numConnections);
}
catch { }
}
}
Thread.Sleep(1000);
}
}
/// <summary>
/// 发送信息
/// </summary>
/// <param name="uid">要发送的用户的uid</param>
/// <param name="msg">消息体</param>
public void Send(string uid, string msg)
{
try
{
if (uid == string.Empty || uid == "" || msg == string.Empty || msg == "")
return;
SocketAsyncEventArgsWithId socketWithId = readWritePool.FindByUID(uid);
if (socketWithId == null)
//说明用户已经断开
//100 发送成功
//200 发送失败
//300 用户不在线
//其它 表示异常的信息
OnSended(uid, "300");
else
{
MySocketAsyncEventArgs e = socketWithId.SendSAEA;
if (e.SocketError == SocketError.Success)
{
int i = 0;
try
{
lock (String.Empty)
{
//string message = @"[lenght=" + msg.Length + @"]" + msg;
string message = msg;
byte[] sendbuffer = System.Text.Encoding.Default.GetBytes(message);
//e.SetBuffer(sendbuffer, 0, sendbuffer.Length);
(e.UserToken as Socket).Send(sendbuffer);
//Boolean willRaiseEvent = (e.UserToken as Socket).SendAsync(e);
//if (!willRaiseEvent)
//{
// this.ProcessSend(e);
//}
}
}
catch (Exception ex)
{
//ICSharpCode.Core.LoggingService.Error("Send错误:" + ex.Message, ex);
//if (i <= 5)
//{
// i++;
// //如果发送出现异常就延迟0.01秒再发
// Thread.Sleep(10);
// Send(uid, msg);
//}
//else
//{
// OnSended(uid, ex.ToString());
//}
OnSended(uid, ex.ToString());
this.CloseClientSocket(((MySocketAsyncEventArgs)e).UID);
}
}
else
{
OnSended(uid, "200");
this.CloseClientSocket(((MySocketAsyncEventArgs)e).UID);
}
}
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketListener>.Error("Send错误:" + ex.Message, ex);
ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
}
}
/// <summary>
/// 停止服务器
/// </summary>
public void Stop()
{
try
{
this.listenFlag = false;
if (listenSocket != null)
listenSocket.Close();
listenSocket = null;
Dispose();
try
{
mutex.ReleaseMutex();
}
catch (ApplicationException ae)
{
ICSharpCode.Core.LoggingService<SocketListener>.Error(ae.Message);
}
serverstate = ServerState.Stoped;
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketListener>.Error("SocketListner Stop错误:" + ex.Message, ex);
ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
}
}
private void StartAccept(SocketAsyncEventArgs acceptEventArg)
{
try
{
if (acceptEventArg == null)
{
acceptEventArg = new SocketAsyncEventArgs();
acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted);
}
else
acceptEventArg.AcceptSocket = null;
this.semaphoreAcceptedClients.WaitOne();
Boolean willRaiseEvent = this.listenSocket.AcceptAsync(acceptEventArg);
if (!willRaiseEvent)
{
this.ProcessAccept(acceptEventArg);
}
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketListener>.Error("SocketListener StartAccept错误:" + ex.Message, ex);
ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
}
}
private void OnAcceptCompleted(object sender, SocketAsyncEventArgs e)
{
this.ProcessAccept(e);
}
private void ProcessAccept(SocketAsyncEventArgs e)
{
lock (readWritePool)
{
try
{
if (e.LastOperation != SocketAsyncOperation.Accept) //检查上一次操作是否是Accept,不是就返回
return;
if (this.State == ServerState.Stoped) return;
if (e.AcceptSocket.RemoteEndPoint == null) //服务器断开连接
return;
IPEndPoint ipEndPoint = e.AcceptSocket.RemoteEndPoint as IPEndPoint;
string UID = GetIDByIP(ipEndPoint.Address.ToString() + ":" + ipEndPoint.Port); //根据IP获取用户的UID
if (UID == string.Empty || UID == null || UID == "")
return;
if (readWritePool.BusyPoolContains(UID)) //判断现在的用户是否已经连接,避免同一用户开两个连接
{
this.CloseClientSocket(UID);
return;
}
SocketAsyncEventArgsWithId readEventArgsWithId = this.readWritePool.Pop(UID);
if (readEventArgsWithId.ReceiveSAEA.SocketError != SocketError.Success && readEventArgsWithId.ReceiveSAEA.SocketError != SocketError.ConnectionReset)
{
readEventArgsWithId.ReceiveSAEA.UserToken = null;
readEventArgsWithId.ReceiveSAEA.Dispose();
readEventArgsWithId.ReceiveSAEA = new MySocketAsyncEventArgs("Receive");
readEventArgsWithId.ReceiveSAEA.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceiveCompleted);
}
if (readEventArgsWithId.SendSAEA.SocketError != SocketError.Success && readEventArgsWithId.SendSAEA.SocketError != SocketError.ConnectionReset)
{
readEventArgsWithId.SendSAEA.UserToken = null;
readEventArgsWithId.SendSAEA.Dispose();
readEventArgsWithId.SendSAEA = new MySocketAsyncEventArgs("Send");
readEventArgsWithId.SendSAEA.Completed += new EventHandler<SocketAsyncEventArgs>(OnSendCompleted);
}
readEventArgsWithId.ReceiveSAEA.UserToken = e.AcceptSocket;
readEventArgsWithId.SendSAEA.UserToken = e.AcceptSocket;
readEventArgsWithId.IsAllowReceive = true;
Interlocked.Increment(ref this.numConnections);
//Console.WriteLine("当前连接:" + this.numConnections);
ICSharpCode.Core.LoggingService<SocketListener>.Debug("当前连接数:" + this.numConnections);
//触发处理客户端连接完成事件
if (this.ProcessAcceptComplete != null)
{
this.ProcessAcceptComplete(UID, e);
}
this.StartAccept(e);
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketListener>.Error("ProcessAccept错误:" + ex.Message, ex);
ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
}
}
}
private void OnReceiveCompleted(object sender, SocketAsyncEventArgs e)
{
ProcessReceive(e);
}
private void OnSendCompleted(object sender, SocketAsyncEventArgs e)
{
//ICSharpCode.Core.LoggingService.Debug("操作类型:" + e.LastOperation);
ProcessSend(e);
}
private void ProcessReceive(SocketAsyncEventArgs e)
{
try
{
lock (String.Empty)
{
if (e.LastOperation != SocketAsyncOperation.Receive)
return;
// 检查如果远程主机关闭了连接
if (e.BytesTransferred > 0)
{
if (e.SocketError == SocketError.Success)
{
Int32 byteTransferred = e.BytesTransferred;
string received = System.Text.Encoding.Default.GetString(e.Buffer, e.Offset, byteTransferred);
OnMsgReceived(((MySocketAsyncEventArgs)e).UID, received);
//检查消息的准确性
//string[] msg = handler.GetActualString(received);
//foreach (string m in msg)
// OnMsgReceived(((MySocketAsyncEventArgs)e).UID, m);
try
{
//可以在这里设一个停顿来实现间隔时间段监听,这里的停顿是单个用户间的监听间隔
//发送一个异步接受请求,并获取请求是否为成功
Boolean willRaiseEvent = (e.UserToken as Socket).ReceiveAsync(e);
if (!willRaiseEvent)
ProcessReceive(e);
}
catch (System.InvalidOperationException ex)
{
//ProcessReceive(e);
}
}
}
else
this.CloseClientSocket(((MySocketAsyncEventArgs)e).UID);
}
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketListener>.Error("ProcessReceive错误:" + ex.Message, ex);
//ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
}
}
private void ProcessSend(SocketAsyncEventArgs e)
{
try
{
// 检查如果远程主机关闭了连接
if (e.SocketError == SocketError.Success)
{
if (e.LastOperation != SocketAsyncOperation.Send)
return;
if (e.BytesTransferred > 0)
{
if (e.SocketError == SocketError.Success)
OnSended(((MySocketAsyncEventArgs)e).UID, "100");
else
OnSended(((MySocketAsyncEventArgs)e).UID, "200");
}
}
else
{
this.CloseClientSocket(((MySocketAsyncEventArgs)e).UID);
}
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketListener>.Error("ProcessSend错误:" + ex.Message, ex);
//ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
}
}
private void CloseClientSocket(string uid)
{
try
{
if (uid == string.Empty || uid == "")
return;
SocketAsyncEventArgsWithId saeaw = readWritePool.FindByUID(uid);
if (saeaw == null)
return;
Socket s = saeaw.ReceiveSAEA.UserToken as Socket;
try
{
s.Shutdown(SocketShutdown.Both);
saeaw.ReceiveSAEA.DisconnectReuseSocket = true;
}
catch (Exception)
{
//客户端已经关闭
//Console.WriteLine("客户端已经关闭!");
ICSharpCode.Core.LoggingService<SocketListener>.Warn("客户端已经关闭!");
}
this.semaphoreAcceptedClients.Release();
Interlocked.Decrement(ref this.numConnections);
this.readWritePool.Push(saeaw);
//出发事件
if (this.OnClientClose != null)
{
this.OnClientClose(uid);
}
//Console.WriteLine("当前连接数:" + this.numConnections);
ICSharpCode.Core.LoggingService<SocketListener>.Debug("当前连接数:" + this.numConnections);
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketListener>.Error("CloseClientSocket错误:" + ex.Message, ex);
//ICSharpCode.Core.LoggingService.Error(ex.StackTrace);
}
}
#region IDisposable Members
public void Dispose()
{
try
{
if (bufferManager != null)
{
bufferManager.Dispose();
bufferManager = null;
}
if (readWritePool != null)
{
readWritePool.Dispose();
readWritePool = null;
}
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketListener>.Error("Dispose错误:" + ex.Message, ex);
ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
}
}
#endregion
/// <summary>
/// 处理接收客户端连接完成事件
/// </summary>
public event EventHandler<SocketAsyncEventArgs> ProcessAcceptComplete;
}
}
SocketClient.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Configuration;
namespace Mesnac.Communication
{
/// <summary>
/// Socket客户端类,连接App.Config中FeedingIP:Port
/// </summary>
public class SocketClient : IDisposable
{
#region 字段、委托、事件
private static SocketClient instance = null;
/// <summary>
/// 客户端连接Socket
/// </summary>
private Socket clientSocket;
/// <summary>
/// 连接状态
/// </summary>
private Boolean connected = false;
/// <summary>
/// 连接点
/// </summary>
private IPEndPoint hostEndPoint;
/// <summary>
/// 连接信号量
/// </summary>
private static AutoResetEvent autoConnectEvent = new AutoResetEvent(false);
/// <summary>
/// 接受到数据时的委托
/// </summary>
/// <param name="info"></param>
public delegate void ReceiveMsgHandler(string info);
/// <summary>
/// 接收到数据时调用的事件
/// </summary>
public event ReceiveMsgHandler OnMsgReceived;
/// <summary>
/// 开始监听数据的委托
/// </summary>
public delegate void StartListenHandler();
/// <summary>
/// 开始监听数据的事件
/// </summary>
public event StartListenHandler StartListenThread;
/// <summary>
/// 发送信息完成的委托
/// </summary>
/// <param name="successorfalse"></param>
public delegate void SendCompleted(bool successorfalse);
/// <summary>
/// 发送信息完成的事件
/// </summary>
public event SendCompleted OnSended;
/// <summary>
/// 监听接收的SocketAsyncEventArgs
/// </summary>
private SocketAsyncEventArgs listenerSocketAsyncEventArgs;
/// <summary>
/// 心跳时钟
/// </summary>
private System.Timers.Timer _timer = null;
/// <summary>
/// SocketServer服务器IP
/// </summary>
public static string hostName;
/// <summary>
/// SocketServer服务器端口号
/// </summary>
public static int port;
#endregion
#region 属性定义
/// <summary>
/// SocketServer服务器IP地址
/// </summary>
public static string ServerIp
{
get
{
return ConfigurationManager.AppSettings["ServerIp"];
}
}
/// <summary>
/// SocketServer服务器端口号
/// </summary>
public static string ServerPort
{
get
{
return ConfigurationManager.AppSettings["Port"];
}
}
/// <summary>
/// 是否处于连接状态,需要通过定时发送心跳信息来驱动连接状态的变化
/// </summary>
public bool IsConnected
{
get
{
if (this.clientSocket == null)
{
return false;
}
return this.clientSocket.Connected;
}
}
/// <summary>
/// TCP通信服务实例
/// </summary>
public static SocketClient Instance
{
get
{
if (instance == null)
{
instance = new SocketClient();
}
return instance;
}
}
#endregion
#region 初始化
/// <summary>
/// 启动服务
/// </summary>
public static void StartService()
{
if (instance == null)
{
instance = new SocketClient();
instance.Connect();
}
}
/// <summary>
/// 初始化客户端
/// </summary>
/// <param name="hostName">服务端地址{IP地址}</param>
/// <param name="port">端口号</param>
public SocketClient()//String hostName, Int32 port
{
this.InitHostEndPoint();
}
/// <summary>
/// 初始化HostEndPoint
/// </summary>
private void InitHostEndPoint()
{
string hostName = ServerIp;
int port = 0;
int.TryParse(ServerPort, out port);
IPAddress address = null;
if (!String.IsNullOrEmpty(hostName))
{
IPAddress.TryParse(hostName, out address);
}
else
{
IPHostEntry host = Dns.GetHostEntry("127.0.0.1");
IPAddress[] addressList = host.AddressList;
foreach (IPAddress ad in addressList)
{
if (ad.AddressFamily == AddressFamily.InterNetwork)
{
address = ad;
break;
}
}
}
this.hostEndPoint = new IPEndPoint(address, port);
}
#endregion
#region 连接
/// <summary>
/// 连接服务端
/// </summary>
public bool Connect()
{
bool result = false;
this.Disconnect();
this.clientSocket = new Socket(this.hostEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs();
connectArgs.UserToken = this.clientSocket;
connectArgs.RemoteEndPoint = this.hostEndPoint;
connectArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnConnect);
result = clientSocket.ConnectAsync(connectArgs);
//等待连接结果
//autoConnectEvent.WaitOne();
SocketError errorCode = connectArgs.SocketError;
if (errorCode == SocketError.Success)
{
listenerSocketAsyncEventArgs = new SocketAsyncEventArgs();
byte[] receiveBuffer = new byte[32768];
listenerSocketAsyncEventArgs.UserToken = clientSocket;
listenerSocketAsyncEventArgs.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
listenerSocketAsyncEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);
StartListenThread += new SocketClient.StartListenHandler(listener_StartListenThread);
StartListenThread();
return result;
}
else
{
ICSharpCode.Core.LoggingService<SocketClient>.Warn(String.Format("连接SocketServer={0}:{1}失败", this.hostEndPoint.Address.ToString(), this.hostEndPoint.Port));
//throw new SocketException((Int32)errorCode);
connectArgs.Dispose();
this.Dispose();
return false;
}
}
/// <summary>
/// 重新连接
/// </summary>
/// <returns></returns>
public bool ReConnect()
{
try
{
this.Dispose();
bool result = this.Connect();
if (result)
{
this.Send("TestConnect");
}
return this.connected;
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketClient>.Error("网络断开:" + ex.Message, ex);
return false;
}
}
/// <summary>
/// 没有连接对象返回false,否则重连
/// </summary>
/// <returns>返回重连结果</returns>
public bool IsOrNoReConnect()
{
try
{
lock (this)
{
if (this.clientSocket == null)
{
return false;
}
return this.ReConnect();
}
}
catch (System.Exception ex)
{
ICSharpCode.Core.LoggingService<SocketClient>.Error("网络已经断开:" + ex.Message);
return false;
}
}
/// <summary>
/// 连接的完成方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnConnect(object sender, SocketAsyncEventArgs e)
{
try
{
//autoConnectEvent.Set();
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketClient>.Error(ex.Message);
}
this.connected = (e.SocketError == SocketError.Success);
}
#endregion
#region 断开连接
/// <summary>
/// 断开连接
/// </summary>
public void Disconnect()
{
if (clientSocket != null)
{
if (clientSocket.Connected)
{
//autoConnectEvent.Close();
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Disconnect(false);
}
StopListenThread();
ICSharpCode.Core.LoggingService<SocketClient>.Debug("断开连接");
}
}
#endregion
#region 心跳
#region 启动心跳时钟
/// <summary>
/// 启动定时器运行服务
/// </summary>
public void StartHeartbeat()
{
if (this._timer == null)
{
this._timer = new System.Timers.Timer();
this._timer.Interval = 2000;
this._timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
this._timer.Start();
}
}
#endregion
#region 停止心跳时钟
/// <summary>
/// 停止定时器运行服务
/// </summary>
public void StopHeartbeat()
{
if (this._timer != null)
{
this._timer.Stop();
this._timer.Dispose();
this._timer = null;
}
}
#endregion
protected void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (this.connected)
{
this.Send("0000"); //发送心跳包
}
else
{
this.ReConnect(); //重新连接
}
}
#endregion
#region 侦听
private void listener_StartListenThread()
{
ICSharpCode.Core.LoggingService<SocketClient>.Debug("开始侦听...");
//receiveThread = new Thread(new ThreadStart(Listen));
Listen();
}
/// <summary>
/// 停止监听线程
/// </summary>
public void StopListenThread()
{
try
{
this.StopHeartbeat();
if (StartListenThread != null)
{
StartListenThread -= new SocketClient.StartListenHandler(listener_StartListenThread);
}
if (this.listenerSocketAsyncEventArgs != null)
{
listenerSocketAsyncEventArgs.Completed -= new EventHandler<SocketAsyncEventArgs>(OnReceive);
this.listenerSocketAsyncEventArgs.UserToken = null;
this.listenerSocketAsyncEventArgs.Dispose();
}
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketClient>.Error("停止监听线程异常:", ex);
}
}
/// <summary>
/// 开始监听线程的入口函数
/// </summary>
public void Listen()
{
try
{
Socket socket = listenerSocketAsyncEventArgs.UserToken as Socket;
if (socket != null)
{
socket.ReceiveAsync(listenerSocketAsyncEventArgs);
if (socket.Connected)
{
this.StartHeartbeat();
}
}
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketClient>.Error("侦听异常!", ex);
}
}
#endregion
#region 消息
/// <summary>
/// 发送信息
/// </summary>
/// <param name="message"></param>
public void Send(String message)
{
if (clientSocket != null && this.connected)
{
Byte[] sendBuffer = Encoding.Default.GetBytes(message);
SocketAsyncEventArgs senderSocketAsyncEventArgs = new SocketAsyncEventArgs();
senderSocketAsyncEventArgs.UserToken = this.clientSocket;
senderSocketAsyncEventArgs.SetBuffer(sendBuffer, 0, sendBuffer.Length);
senderSocketAsyncEventArgs.RemoteEndPoint = this.hostEndPoint;
senderSocketAsyncEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);
clientSocket.SendAsync(senderSocketAsyncEventArgs);
}
else
{
//throw new SocketException((Int32)SocketError.NotConnected);
ICSharpCode.Core.LoggingService<SocketClient>.Warn("Socket未初始化或未连接!");
}
}
/// <summary>
/// 接收的完成方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnReceive(object sender, SocketAsyncEventArgs e)
{
try
{
if (e.BytesTransferred > 0)
{
string msg = Encoding.Default.GetString(e.Buffer, 0, e.BytesTransferred);
ICSharpCode.Core.LoggingService<SocketClient>.Debug("接收到数据" + msg);
Listen();
if (OnMsgReceived != null)
OnMsgReceived(msg);
}
}
catch (Exception ex)
{
ICSharpCode.Core.LoggingService<SocketClient>.Error("接收数据异常:" + ex.Message, ex);
}
}
/// <summary>
/// 发送的完成方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnSend(object sender, SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
//触发事件
if (OnSended != null)
{
OnSended(true);
}
}
else
{
//触发事件
if (OnSended != null)
{
OnSended(false);
}
this.ProcessError(e);
}
}
/// <summary>
/// 处理错误
/// </summary>
/// <param name="e"></param>
private void ProcessError(SocketAsyncEventArgs e)
{
Socket s = e.UserToken as Socket;
if (s != null && s.Connected)
{
try
{
s.Shutdown(SocketShutdown.Both);
}
catch (Exception)
{
//client already closed
}
finally
{
if (s.Connected)
{
s.Close();
}
}
}
//throw new SocketException((Int32)e.SocketError);
}
#endregion
#region IDisposable Members
public void Dispose()
{
this.Disconnect();
if (clientSocket != null)
{
this.clientSocket.Close();
this.clientSocket.Dispose();
this.clientSocket = null;
}
}
#endregion
}
}