最近写了两个异步socket组件:
在SocketLibrary里面有两个TCP异步通信组件,分别是:AsyncTCPServer, AsyncTCPClient,同时里面包含测试程序
经过测试,客户端连接达到10000个以上的情况下,通信正常。
如果有什么问题或建议请给我发邮件:michelsn#163.com (请把 # 用 @ 替换掉)
/*
*
* 作者:俞伟
* 时间:2007-11-29
* 作用:声明AsyncTCPServer类,TCP异步通信服务端
* 邮件:michelsn@163.com
*
* */
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace SocketLibrary {
public partial class AsyncTCPServer : Component {
#region 构造函数
public AsyncTCPServer() {
InitializeComponent();
}
public AsyncTCPServer(IContainer container) {
container.Add(this);
InitializeComponent();
}
#endregion
#region 私有变量
private Socket mSocket = null;
private string keyID = "";
private bool active = false;
private ArrayList clientSocketList = new ArrayList();
private bool IsExit = false;
#endregion
#region 变量属性
/// <summary>
/// Socket标志
/// </summary>
public string KeyID {
get {
return keyID;
}
}
/// <summary>
/// Socket通信状态
/// </summary>
public bool Active {
get {
return active;
}
}
/// <summary>
/// 消息的终止判断符
/// </summary>
public static string EndChar {
get {
return new string((char)0, 1);
}
}
/// <summary>
/// 客户端管理队列
/// </summary>
public ArrayList ClientSocketList {
get {
return clientSocketList;
}
}
#endregion
#region 代理委托
/// <summary>
/// Socket异常错误事件
/// </summary>
/// <param name="aKeyID">异常错误所有者的标志值</param>
/// <param name="aErrorMessage">异常错误信息</param>
public delegate void SocketErrorHandler(string aKeyID, string aErrorMessage);
/// <summary>
/// 停止Socket通信之前
/// </summary>
/// <param name="aAsyncTCPServer">AsyncTCPServer对象</param>
public delegate void BeforeStopHandler(AsyncTCPServer aAsyncTCPServer);
/// <summary>
/// 停止Socket通信之后
/// </summary>
/// <param name="aAsyncTCPServer">AsyncTCPServer</param>
public delegate void AfterStopHandler(AsyncTCPServer aAsyncTCPServer);
/// <summary>
/// 接受新的Socket通信连接请求
/// </summary>
/// <param name="aNewSocket">新接受的Socket通信连接对象</param>
public delegate void AcceptSocketHandler(Socket aNewSocket);
/// <summary>
/// 接收二进制数据
/// </summary>
/// <param name="aKeyID">接收到数据的Socket标志</param>
/// <param name="aData">接收到的数据</param>
/// <param name="aSocket">接收到数据的Socket</param>
public delegate void BinaryDataAvailableHandler(string aKeyID, byte[] aData, SocketObject aSocketObject);
/// <summary>
/// 接收字符串数据
/// </summary>
/// <param name="aKeyID">接收到数据的Socket标志</param>
/// <param name="aData">接收到的数据</param>
/// <param name="aSocket">接收到数据的Socket</param>
public delegate void StringDataAvailableHandler(string aKeyID, string aData, SocketObject aSocketObject);
/// <summary>
/// 客户端断开连接
/// </summary>
/// <param name="aKeyID">客户端对应的Socket标志</param>
public delegate void CloseClientSocketHandler(string aKeyID);
#endregion
#region 事件声明
public event SocketErrorHandler OnSocketError;
public event BeforeStopHandler OnBeforeStop;
public event AfterStopHandler OnAfterStop;
public event AcceptSocketHandler OnAcceptClientSocket;
public event BinaryDataAvailableHandler OnBinaryDataAvailable;
public event StringDataAvailableHandler OnStringDataAvailable;
public event CloseClientSocketHandler OnCloseClientSocket;
#endregion
#region 事件代理方法
/// <summary>
/// 显示异常错误信息
/// </summary>
/// <param name="aKeyID">异常错误所有者的标志值</param>
/// <param name="aErrorMessage">异常错误信息</param>
private void DisplayError(string aKeyID, string aErrorMessage) {
if (OnSocketError != null) {
OnSocketError(aKeyID, aErrorMessage);
}
}
/// <summary>
/// 停止Socket通信之前
/// </summary>
/// <param name="aAsyncTCPServer">AsyncTCPServer对象</param>
private void BeforeStop(AsyncTCPServer aAsyncTCPServer) {
if (OnBeforeStop != null) {
OnBeforeStop(aAsyncTCPServer);
}
}
<summary>
/// 停止Socket通信之后
/// </summary>
/// <param name="aAsyncTCPServer">AsyncTCPServer</param>
private void AfterStop(AsyncTCPServer aAsyncTCPServer) {
if (OnAfterStop != null) {
OnAfterStop(aAsyncTCPServer);
}
}
/// <summary>
/// 接受新的Socket通信连接请求
/// </summary>
/// <param name="aNewSocket">新接受的Socket通信连接对象</param>
public void AcceptClientSocket(Socket aNewSocket) {
if (OnAcceptClientSocket != null) {
OnAcceptClientSocket(aNewSocket);
}
}
/// <summary>
/// 接收二进制数据
/// </summary>
/// <param name="aKeyID">接收到数据的Socket标志</param>
/// <param name="aData">接收到的数据</param>
/// <param name="aSocket">接收到数据的Socket</param>
public void BinaryDataAvailable(string aKeyID, byte[] aData, SocketObject aSocketObject) {
if (OnBinaryDataAvailable != null) {
OnBinaryDataAvailable(aKeyID, aData, aSocketObject);
}
}
/// <summary>
/// 接收字符串数据
/// </summary>
/// <param name="aKeyID">接收到数据的Socket标志</param>
/// <param name="aData">接收到的数据</param>
/// <param name="aSocket">接收到数据的Socket</param>
public void StringDataAvailable(string aKeyID, string aData, SocketObject aSocketObject) {
if (OnStringDataAvailable != null) {
OnStringDataAvailable(aKeyID, aData, aSocketObject);
}
}
/// <summary>
/// 客户端断开连接
/// </summary>
/// <param name="aKeyID">客户端对应的Socket标志</param>
public void CloseClientSocket(string aKeyID) {
if (OnCloseClientSocket != null) {
OnCloseClientSocket(aKeyID);
}
}
#endregion
#region 内部方法
/// <summary>
/// 初始化Socket连接
/// </summary>
/// <param name="aLocalIPAddress">本机地址</param>
/// <param name="aLocalPort">本机端口</param>
/// <returns>返回操作是否成功</returns>
private bool InitSocket(string aLocalIPAddress, int aLocalPort) {
bool bActive = false;
mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
LingerOption lo = new LingerOption(false, 10);
mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);
try {
IPAddress ip = Dns.GetHostAddresses(aLocalIPAddress)[0];
IPEndPoint ipe = new IPEndPoint(ip, aLocalPort);
keyID = Guid.NewGuid().ToString();
mSocket.Bind(ipe);
bActive = true;
} catch (Exception ex) {
bActive = false;
DisplayError(KeyID, ex.Message);
}
return bActive;
}
/// <summary>
/// 监听
/// </summary>
/// <param name="aLimitAcceptCount">挂起连接队列的最大长度</param>
/// <returns>返回操作是否成功</returns>
private bool Listen(int aLimitAcceptCount) {
bool bActive = false;
try {
if (mSocket != null) {
mSocket.Listen(aLimitAcceptCount);
//调用异步接收Socket连接请求事件
mSocket.BeginAccept(new AsyncCallback(AsyncAcceptSocket), mSocket);
bActive = true;
}
} catch (Exception ex) {
bActive = false;
DisplayError(KeyID, ex.Message);
}
return bActive;
}
/// <summary>
/// 主动关闭客户端连接
/// </summary>
/// <param name="aSocketObject">客户端对象</param>
private void CloseClientSocket(SocketObject aSocketObject) {
try {
if (aSocketObject.WorkSocket.Connected) {
aSocketObject.WorkSocket.Shutdown(SocketShutdown.Both);
aSocketObject.WorkSocket.Close();
aSocketObject.WorkSocket = null;
ClientSocketList.Remove(aSocketObject);
}
OnCloseClientSocket(aSocketObject.KeyID);
} catch (Exception ex) {
DisplayError(aSocketObject.KeyID, ex.Message);
}
}
/// <summary>
/// 客户端Socket连接异步接收数据
/// </summary>
/// <param name="ar"></param>
private void AsyncClientSocketReceive(IAsyncResult ar) {
SocketObject so = (SocketObject)ar.AsyncState;
try {
if (so.WorkSocket.Connected) {
int iReceiveCount = so.WorkSocket.EndReceive(ar);
if (iReceiveCount > 0) {
so.sbBuffer.Append(Encoding.UTF8.GetString(so.Buffer, 0, iReceiveCount));
string strReceive = so.sbBuffer.ToString();
if (strReceive.Substring(strReceive.Length - 1, 1) == EndChar) {
//本次接收
strReceive = strReceive.Remove(strReceive.Length - 1, 1);
//调用外部用户接口方法
BinaryDataAvailable(so.KeyID, Encoding.UTF8.GetBytes(strReceive), so);
StringDataAvailable(so.KeyID, strReceive, so);
//清空数据
so.sbBuffer.Remove(0, so.sbBuffer.Length);
}
if (IsExit == false) {
so.WorkSocket.BeginReceive(so.Buffer, 0, so.Buffer.Length, SocketFlags.None, new AsyncCallback(AsyncClientSocketReceive), so);
}
} else {
CloseClientSocket(so);
}
} else {
CloseClientSocket(so);
}
} catch (Exception ex) {
//接收数据异常,则关闭该客户端连接
CloseClientSocket(so);
DisplayError(so.KeyID, ex.Message);
}
}
/// <summary>
/// 异步接受Socket连接请求
/// </summary>
/// <param name="ar">IAsyncResult接口对象</param>
private void AsyncAcceptSocket(IAsyncResult ar) {
Socket sock = (Socket)ar.AsyncState;
try {
if (IsExit == false) {
Socket handler = sock.EndAccept(ar);
AcceptClientSocket(handler);
//判断handler是不是被设置为null,如果为null表示连接在执行AcceptSocket过程中用户在OnAcceptSocket中把连接释放掉
if (handler != null) {
//判断是否保持连接,如果为false,表示连接在执行AcceptSocket过程中用户在OnAcceptSocket中把连接断开掉
if (handler.Connected) {
SocketObject so = new SocketObject();
so.KeyID = Guid.NewGuid().ToString();
so.WorkSocket = handler;
ClientSocketList.Add(so);
if (IsExit == false) {
so.WorkSocket.BeginReceive(so.Buffer, 0, so.Buffer.Length, SocketFlags.None, new AsyncCallback(AsyncClientSocketReceive), so);
}
} else {
handler = null;
}
}
if (IsExit == false) {
sock.BeginAccept(new AsyncCallback(AsyncAcceptSocket), sock);
}
}
} catch (Exception ex) {
//接受连接过程发生异常关闭连接
Stop();
DisplayError(KeyID, ex.Message);
}
}
/// <summary>
/// 通过客户端Socket异步发送消息
/// </summary>
/// <param name="ar">IAsyncResult接口对象</param>
private void AsyncClientSend(IAsyncResult ar) {
SocketObject so = (SocketObject)ar.AsyncState;
try {
int iSendCount = so.WorkSocket.EndSend(ar);
} catch (Exception ex) {
DisplayError(so.KeyID, ex.Message);
}
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="aData">要发送的消息</param>
/// <param name="aSocketObject">接收消息的对象</param>
private void Send(byte[] aData, SocketObject aSocketObject) {
try {
aSocketObject.WorkSocket.BeginSend(aData, 0, aData.Length, SocketFlags.None, new AsyncCallback(AsyncClientSend), aSocketObject);
} catch (Exception ex) {
DisplayError(aSocketObject.KeyID, ex.Message);
}
}
#endregion
#region 开放的接口方法
/// <summary>
/// 启动Socket通信
/// </summary>
/// <param name="aLocalIPAddress">本机地址</param>
/// <param name="aLocalPort">本机端口</param>
/// <param name="aLimitAcceptCount">挂起连接队列的最大长度</param>
/// <returns>返回操作是否成功</returns>
public bool Start(string aLocalIPAddress, int aLocalPort, int aLimitAcceptCount) {
bool bActive = InitSocket(aLocalIPAddress, aLocalPort);
if (bActive) {
bActive = Listen(aLimitAcceptCount);
}
active = bActive;
return active;
}
/// <summary>
/// 停止Socket通信
/// </summary>
/// <returns>返回操作是否成功</returns>
public bool Stop() {
bool bActive = false;
if (mSocket != null) {
//之前
BeforeStop(this);
try {
IsExit = true;
Thread.Sleep(10);
if (mSocket.Connected) {
mSocket.Shutdown(SocketShutdown.Both);
}
mSocket.Close();
mSocket = null;
bActive = true;
} catch (Exception ex) {
bActive = false;
DisplayError(KeyID, ex.Message);
}
active = !bActive;
//之后
if (bActive) {
AfterStop(this);
}
}
return bActive;
}
/// <summary>
/// 发送消息(异步发送)
/// </summary>
/// <param name="aMessage">要发送的消息</param>
public void Send(string aMessage, SocketObject aSocketObject) {
string strMessage = aMessage;
//判断要发送的消息是不是以消息终止判断符号结尾,如果没有则自动加上
if (strMessage.Substring(strMessage.Length - 1, 1) != EndChar) {
strMessage = strMessage + EndChar;
}
Send(Encoding.UTF8.GetBytes(strMessage), aSocketObject);
}
/// <summary>
/// 发送消息(异步发送)
/// </summary>
/// <param name="aMessage">要发送的消息</param>
public void Send(byte[] aMessage, int aMessageLength, SocketObject aSocketObject) {
StringBuilder SendBuffer = new StringBuilder();
SendBuffer.Append(Encoding.UTF8.GetString(aMessage, 0, aMessageLength));
string strSend = SendBuffer.ToString();
Send(strSend, aSocketObject);
}
/// <summary>
/// 广播消息
/// </summary>
/// <param name="aMessage">要广播的消息</param>
public void BroadcastMessage(string aMessage) {
string strMessage = aMessage;
//判断要发送的消息是不是以消息终止判断符号结尾,如果没有则自动加上
if (strMessage.Substring(strMessage.Length - 1, 1) != EndChar) {
strMessage = strMessage + EndChar;
}
for (int i = 0; i < ClientSocketList.Count; i++) {
SocketObject so = (SocketObject)ClientSocketList[i];
try {
Send(Encoding.UTF8.GetBytes(strMessage), so);
} catch (Exception ex) {
DisplayError(so.KeyID, ex.Message);
}
}
}
#endregion
}
}