C# 实现的多线程异步Socket数据包接收器框架(2)

转载自 zhonghuafy

下面是创建侦听Socket对象的方法代码。

Code
/// <summary>
/// 创建接收服务器的 Socket, 并侦听客户端连接请求
/// </summary>
private bool CreateReceiverSocket()
{
try
{
_receiverSocket
=new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_receiverSocket.Bind(
new IPEndPoint(IPAddress.Any, _tcpSocketPort));// 绑定端口
_receiverSocket.Listen(_maxAllowListenQueueLength);// 开始监听

return true;
}
catch
{
this.OnReceiverException();
return false;
}
}

3.2 侦听客户端连接请求

服务器端循环等待客户端连接请求。一旦有请求,先判断客户端连接数是否超限,接着检测该客户端IP地址,一切正常后建立TSession对象,并调用异步方法接收客户端Socket数据包。

代码中,Socket读到数据时的回调AsyncCallback委托方法EndReceiveData()完成数据接收工作,正常情况下启动另一个异步BeginReceive()调用。

.NET中,每个异步方法都有自己的独立线程,异步处理其实也基于多线程机制的。下面代码中的异步套异步调用,既占用较大的系统资源,也给处理带来意想不到的结果,更是出现异常时难以控制和处理的关键所在。

Code
/// <summary>
/// 循环侦听客户端请求,由于要用线程池,故带一个参数
/// </summary>
private void ListenClientRequest(object state)
{
Socket client
=null;
while (!_stopReceiver)
{
if (_stopConnectRequest)// 停止客户端连接请求
{
if (_receiverSocket!= null)
{
try
{
_receiverSocket.Close();
// 强制关闭接收器
}
catch
{
this.OnReceiverException();
}
finally
{
// 必须为 null,否则 disposed 对象仍然存在,将引发下面的错误
_receiverSocket =null;
}
}
continue;
}
else
{
if (_receiverSocket== null)
{
if (!this.CreateReceiverSocket())
{
continue;
}
}
}

try
{
if (_receiverSocket.Poll(_loopWaitTime, SelectMode.SelectRead))
{
// 频繁关闭、启动时,这里容易产生错误(提示套接字只能有一个)
client = _receiverSocket.Accept();

if (client != null&& client.Connected)
{
if (this._clientCount>= this._maxAllowClientCount)
{
this.OnReceiverException();

try
{
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch { }
}
else if (CheckSameClientIP(client))// 已存在该 IP 地址
{
try
{
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch { }
}
else
{
TSession session
=new TSession(client);
session.LoginTime
= DateTime.Now;

lock (_sessionTable)
{
int preSessionID= session.ID;
while (true)
{
if (_sessionTable.ContainsKey(session.ID))// 有可能重复该编号
{
session.ID
=100000 + preSessionID;
}
else
{
break;
}
}
_sessionTable.Add(session.ID, session);
// 登记该会话客户端
Interlocked.Increment(ref _clientCount);
}

this.OnClientRequest();

try // 客户端连续连接或连接后立即断开,易在该处产生错误,系统忽略之
{
// 开始接受来自该客户端的数据
session.ClientSocket.BeginReceive(session.ReceiveBuffer,0,
session.ReceiveBufferLength, SocketFlags.None, EndReceiveData, session);
}
catch
{
session.DisconnectType
= TDisconnectType.Exception;
session.State
= TSessionState.NoReply;
}
}
}
else if (client != null)// 非空,但没有连接(connected is false)
{
try
{
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch { }
}
}
}
catch
{
this.OnReceiverException();

if (client != null)
{
try
{
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch { }
}
}
// 该处可以适当暂停若干毫秒
}
// 该处可以适当暂停若干毫秒
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值