打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
C#基于事件机制的Socket服务类 | 布谷中国网

C#基于事件机制的Socket服务类

时间: 2011-12-08 / 分类: Winfrom / 浏览次数: 5 次 / 0个评论 发表评论

调用示例

 

class Program
{
static void Main(string[] args)
{
TCPServer.TcpServer tcpserver = new TCPServer.TcpServer(3344);
tcpserver.SessionTimeOut = 50000;
tcpserver.OnError += new ThrowError(tcpserver_OnError);
tcpserver.OnServerStart += new TcpServerEvent(tcpserver_OnServerStart);
tcpserver.OnServerStop += new TcpServerEvent(tcpserver_OnServerStop);
tcpserver.OnSessionClosed += new TcpServerEvent(tcpserver_OnSessionClosed);
tcpserver.OnSessionCreated += new TcpServerEvent(tcpserver_OnSessionCreated);
tcpserver.OnSessionFull += new TcpServerEvent(tcpserver_OnSessionFull);
Console.WriteLine(“           TCPServer author:Yi Dongliang  www.bugucn.com“);
Console.WriteLine(“”);
do
{
Console.Write(“TCPServer>”);
string cmd = Console.ReadLine().ToUpper();
if (cmd==”START”)
{
tcpserver.Start();
}
if (cmd==”STOP”)
{
tcpserver.Stop();
}
} while (true);
}

static void tcpserver_OnSessionFull(object sender, string param)
{
Console.WriteLine(“Session is full!”);
}

static void tcpserver_OnSessionCreated(object sender, string param)
{
SocketSession socket = (SocketSession)sender;
Console.WriteLine(“New Session Created.” + socket.ClientIp);
socket.OnError += new ThrowError(socket_OnError);
socket.OnRecData += new RecData(socket_OnRecData);
}

static void socket_OnRecData(string AcceptStr, SocketSession sctSession)
{
Console.WriteLine(AcceptStr);
if (AcceptStr.Contains(“<NO>”))
{
sctSession.SendBackData(“test backData”);
System.Threading.Thread.Sleep(1000);
sctSession.StopSession();
}
}

static void socket_OnError(Exception e, object sender)
{
SocketSession socket = (SocketSession)sender;
Console.WriteLine(“ClientSocket Error:” + socket.ClientIp +e.StackTrace+”——-”+e.Message);
}

static void tcpserver_OnSessionClosed(object sender, string param)
{
SocketSession socket = (SocketSession)sender;
Console.WriteLine(“New Session Closed.” + socket.ClientIp);
}

static void tcpserver_OnServerStop(object sender, string param)
{
Console.WriteLine(“Server Stop.”);
}

static void tcpserver_OnServerStart(object sender, string param)
{
Console.WriteLine(“Server Start.”+((TcpServer)sender).Port);
}

static void tcpserver_OnError(Exception e, object sender)
{

Console.WriteLine(“/r异常:” + e.Message + e.StackTrace);
}

 

 

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace TCPServer
{
public class TcpServer
{
#region Attrib
private Socket listener;
private int _port = 4999;
private int _MaxQueue = 10000;
private bool _IsRuning = false;
private double _sessionTimeOut = 3;
private static ManualResetEvent allDone = new ManualResetEvent(false);//监听用户连接的线程与处理线程之间的同步管理
private IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, 4999);
private SocketSession[] sessionList;
/// <summary>
/// 会话列表
/// </summary>
public SocketSession[] SessionList
{
get { return sessionList; }
}
/// <summary>
/// 获取服务器是否运行
/// </summary>
public bool IsRuning
{
get { return _IsRuning; }
}

/// <summary>
/// 获取或设置会话超时
/// </summary>
public double SessionTimeOut
{
get { return _sessionTimeOut; }
set { _sessionTimeOut = value; }
}
/// <summary>
/// 获取最大链接数
/// </summary>
public int MaxQueue
{
get { return _MaxQueue; }
}
/// <summary>
/// 获取当前连接数
/// </summary>
public int CurrentClientCount
{
get
{
int n = 0;
for (int i = 0; i < this.MaxQueue;i++ )
{
if(this.sessionList[i]!=null)
n++;
}
return n;
}
}
/// <summary>
/// 获取监听端口。
/// </summary>
public int Port
{
get { return _port; }
}
#endregion

#region Event
/// <summary>
/// 服务启动事件
/// </summary>
public event TcpServerEvent OnServerStart;
/// <summary>
/// 服务停止事件
/// </summary>
public event TcpServerEvent OnServerStop;
/// <summary>
/// 当产生异常时触发
/// </summary>
public event ThrowError OnError;
/// <summary>
/// 当会话创建时发生
/// </summary>
public event TcpServerEvent OnSessionCreated;
/// <summary>
/// 当会话关闭时发生
/// </summary>
public event TcpServerEvent OnSessionClosed;
/// <summary>
/// 当会话已达到最大上限时发生。
/// </summary>
public event TcpServerEvent OnSessionFull;
#endregion

#region 构造函数

/// <summary>
///  使用指定的端口初始化Socket对象。
/// </summary>
/// <param name=”ListenPort”>指定端口</param>
public TcpServer(int ListenPort)
{
if (ListenPort <= 0 || ListenPort > 65535)
{
OnError(new Exception(“端口超出范围,重置端口为:4999″), this);
_port = 4999;
}
else
_port = ListenPort;
_MaxQueue = 10000;
ipLocal = new IPEndPoint(IPAddress.Any, _port);
}
/// <summary>
/// 使用指定的端口,及最大链接数初始化Socket对象。
/// </summary>
/// <param name=”ListenPort”>需要监听的端口</param>
/// <param name=”maxQueue”>最大链接数</param>
public TcpServer(int ListenPort, int maxQueue)
{
if (ListenPort <= 0 || ListenPort > 65535)
{
OnError(new Exception(“端口超出范围,重置端口为:4999″), this);
_port = 4999;
}
else
{
_port = ListenPort;
}
_MaxQueue = maxQueue;
ipLocal = new IPEndPoint(IPAddress.Any, _port);

}

/// <summary>
/// 使用指定的端口,队列长度,需要监听的IP地址创建Scoket服务器。
/// </summary>
/// <param name=”ListenPort”>监听的端口</param>
/// <param name=”maxQueue”>队列长度</param>
/// <param name=”ipStr”>IP地址</param>
public TcpServer(int ListenPort, int maxQueue, string ipStr)
{
if (ListenPort <= 0 || ListenPort > 65535)
{
OnError(new Exception(“端口超出范围,重置端口为:4999″), this);
_port = 4999;
}
else
_port = ListenPort;
_MaxQueue = maxQueue;
ipLocal = new IPEndPoint(IPAddress.Parse(ipStr), _port);

}
#endregion

#region 开启、停止服务
/// <summary>
///  开启服务
/// </summary>
public void Start()
{
if (_IsRuning)
return;
_IsRuning = true;
//连接上线列表
sessionList = new SocketSession[_MaxQueue];
// Create a TCP/IP socket.
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);

// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(ipLocal);
listener.Listen(_MaxQueue);
ThreadPool.QueueUserWorkItem(new WaitCallback(BeginAcceptConn));
StartSession();
OnServerStart(this, “”);
}
catch (Exception e)
{
OnError(e, this);
}

}
private void BeginAcceptConn(object obj)
{
try
{
while (true)
{
if (!this.IsRuning)
return;
// Set the event to nonsignaled state.
allDone.Reset();

// Start an asynchronous socket to listen for connections.
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);

// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (System.Exception e)
{
OnError(e, this);
}
}
/// <summary>
/// 接收用户连接,开启新线程处理新的连接
/// </summary>
/// <param name=”ar”>新链接的socket对象</param>
private void AcceptCallback(IAsyncResult ar)
{
allDone.Set();
try
{
bool IsNeedWait = true;
do
{
for (int i = 0; i < this._MaxQueue; i++)
{
if (!_IsRuning)
return;
//查找队列空余
if (this.sessionList[i] == null)
{
Socket handler = listener.EndAccept(ar);
//获取客户端链接,创建会话。
SocketSession sckObj = new SocketSession(handler);
this.sessionList[i] = sckObj;
OnSessionCreated(sckObj, “”);
IsNeedWait = false;
break;
}
}
if (IsNeedWait)//队列已满,排队等待。
{
OnSessionFull(this, “”);
Thread.Sleep(600);
}
} while (IsNeedWait);
}
catch (System.Exception e)
{
OnError(e, this);
}
}
/// <summary>
/// 停止服务。
/// </summary>
public void Stop()
{
if (!_IsRuning)
return;
_IsRuning = false;
try
{   //停止监听的socket
this.listener.Close();
}
catch (System.Exception e)
{
OnError(e, this);
}
//停止所有的会话连接及线程。
for (int i = 0; i < this.sessionList.Length; i++)
{
StopSession(ref this.sessionList[i]);
}
OnServerStop(this,”");
}
#endregion

#region 开启线程遍历Session
private void StartSession()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(SessionFor));
}
private void SessionFor(object obj)
{
do
{
for (int i = 0; i < this.sessionList.Length; i++)
{
if (sessionList[i] != null)
{
//清除超时的
DateTime outT = sessionList[i].LastActively.AddSeconds(this.SessionTimeOut);
int n = DateTime.Now.CompareTo(outT);
if (n > 0)//超时
{
OnSessionClosed(sessionList[i],”");
StopSession(ref sessionList[i]);

}
//清除连接已关闭的。
if (sessionList[i] != null && !sessionList[i].ClientSocket.Connected)
{
OnSessionClosed(sessionList[i],”");
StopSession(ref sessionList[i]);
}
}
}
Thread.Sleep(400); //session过期时间单位为秒,停顿400毫秒遍历一次Session
} while (true);
}

/// <summary>
/// 停止某个会话。
/// </summary>
/// <param name=”scs”></param>
private void StopSession(ref SocketSession scs)
{
if (scs != null)
scs.StopSession();
scs = null;
}
#endregion
}

/// <summary>
/// 处理客户端连接的对象
/// </summary>
public class SocketSession
{
#region Event、Message
/// <summary>
/// 当接收到数据时触发。
/// </summary>
public event RecData OnRecData;
/// <summary>
/// SocketSession产生异常
/// </summary>
public event ThrowError OnError;
#endregion

#region Attrib
private string clientIp;
/// <summary>
/// 工作Socket
/// </summary>
private Socket _ClientSocket = null;
/// <summary>
/// Socket每次接收的字节数
/// </summary>
public const int BufferSize = 2048;
/// <summary>
/// Soket 接收字节的数组
/// </summary>
public byte[] buffer = new byte[BufferSize];
/// <summary>
/// 最后活跃时间。
/// </summary>
public DateTime LastActively = DateTime.Now;
/// <summary>
/// 客户端的IP信息
/// </summary>
public string ClientIp
{
get { return clientIp; }
}
/// <summary>
/// 接收到的数据
/// </summary>
public StringBuilder AcceptContent = new StringBuilder();
/// <summary>
/// 客户端Socket
/// </summary>
public Socket ClientSocket
{
get { return _ClientSocket; }
}
/// <summary>
/// 客户端连接会话对象
/// </summary>
/// <param name=”clientSckt”></param>
public SocketSession(Socket clientSckt)
{
this.LastActively = DateTime.Now;
if (clientSckt == null)
throw new Exception(“请指定客户端链接的Socket!”);
this._ClientSocket = clientSckt;
this.clientIp = ClientSocket.RemoteEndPoint.ToString();
RecData(clientSckt);
}
#endregion

#region  Accept、Delay

/// <summary>
/// 开始接收每个线程中的数据
/// </summary>
/// <param name=”socketObj”>数据接收的socket</param>
private void RecData(object socketObj)
{
Socket socketAccept = (Socket)socketObj;
try
{
socketAccept.BeginReceive(buffer, 0, buffer.Length, 0, new AsyncCallback(ReadCallback), socketAccept);
}
catch (System.Exception e)
{
OnError(e, this);
}
}

/// <summary>
/// 开始处理Socket中接收到的buffer,每次接受到数据都会调用数据处理委托
/// </summary>
/// <param name=”ar”></param>
private void ReadCallback(IAsyncResult ar)
{
//修改最后激活时间
this.LastActively = DateTime.Now;
Socket sc = (Socket)ar.AsyncState;
int bytesRead = 0;
try
{
if (this.ClientSocket.Connected)
bytesRead = this.ClientSocket.EndReceive(ar);
}
catch (System.Exception e)
{
OnError(e, this);
}

if (bytesRead > 0)
{
string tmp = System.Text.Encoding.Default.GetString(buffer, 0, bytesRead);
AcceptContent.Append(tmp);
//处理接收到的数据。
OnRecData(AcceptContent.ToString(), this);
if (sc.Connected)
{
ClientSocket.BeginReceive(buffer, 0, BufferSize, 0, new AsyncCallback(ReadCallback), sc);
}
else
{
return;
}
}
else
{
//重置收到的数据对象
AcceptContent = new StringBuilder();
return;
}

}
/// <summary>
/// 从指定的客户链接的Socket返回信息。(一般在接收到数据的处理委托中调用)
/// </summary>
/// <param name=”ReSend”>需要返回的信息</param>
public void SendBackData(string ReSend)
{
try
{
byte[] byteData = System.Text.Encoding.ASCII.GetBytes(ReSend);
this.ClientSocket.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), this.ClientSocket);
}
catch (Exception ee)
{
OnError(ee, this);
}
}
private void SendCallback(System.IAsyncResult ar)
{
try
{
Socket skBk = (Socket)ar.AsyncState;
int bytesSent = skBk.EndSend(ar);
}
catch (System.Exception e)
{
OnError(e, this);
}
}
/// <summary>
/// 停止会话,将关闭ClientSocket
/// </summary>
public void StopSession()
{
try
{
this.ClientSocket.Shutdown(SocketShutdown.Both);
this.ClientSocket.Close();
}
catch (System.Exception e)
{
OnError(e, this);
}
}
#endregion

}

#region delegate、enum
/// <summary>
/// TCPServer产生的事件
/// </summary>
/// <param name=”sender”>事件产生对象</param>
/// <param name=”param”>参数</param>
public delegate void TcpServerEvent(Object sender, string param);
/// <summary>
/// 委托 处理服务器接受到的数据
/// </summary>
/// <param name=”AcceptStr”>接受到的数据</param>
/// <param name=”sctSession”>客户端链接会话。</param>
/// <returns></returns>
public delegate void RecData(string AcceptStr, SocketSession sctSession);
/// <summary>
/// 抛出异常
/// </summary>
/// <param name=”e”>Exception e</param>
/// <param name=”sender”>异常抛出者</param>
public delegate void ThrowError(Exception e,object sender);
#endregion
}

//////////

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
C#中Socket通信编程的同步实现
Socket编程 (连接,发送消息) (Tcp、Udp)
C# TCP 客户端代码
C#+flash socket 聊天程序
C#之Socket操作类实例解析
高性能Socket设计实现 - 志良的技术博客 - 博客园
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服