以前在网上找到的一篇c#异步socket的文章,在使用过程中老是发现消息丢失、消息被截断、串消息的问题,近日看代码时无意中发现一个重大BUG,如下:
/// <summary>
/// 接受数据完成处理函数,异步的特性就体现在这个函数中,
/// 收到数据后,会自动解析为字符串报文
/// </summary>
/// <param name="iar">目标客户端Socket</param>
protected virtual void ReceiveData(IAsyncResult iar)
{
Socket client = (Socket)iar.AsyncState;try
{
//如果两次开始了异步的接收,所以当客户端退出的时候
//会两次执行EndReceiveint recv = client.EndReceive(iar);
if( recv == 0 )
{
//正常的关闭
CloseClient(client, Session.ExitType.NormalExit);
return;
}string receivedData = _coder.GetEncodingString( _recvDataBuffer, recv );
//发布收到数据的事件
if(RecvData!=null)
{...............................
以上代码是异步socket接收消息的方法,每个连接都会有一个线程来进行消息的接收,但是,_recvDataBuffer 却是全局变量:
/// <summary>
/// 接收数据缓冲区
/// </summary>
private byte[] _recvDataBuffer;
如果是放在client中,那是没有问题的,我们做的程序客户端只有一个socket连接,连接到server端,所以不会有问题。但是,在server端就不行了,多个消息接收方法使用了同一个消息接收缓冲区,在多个并发下,经常发生一些不可思议的情况。
我的解决方法:
定义:
/// <summary>
/// 消息接收缓冲区列表,线程安全
/// </summary>
private Hashtable RecvDataHash = Hashtable.Synchronized(new Hashtable());
AcceptConn方法:
//定义该连接的数据接收缓冲区
byte[] myData = new byte[DefaultBufferSize];
RecvDataHash.Add(client, myData);
//开始接收
client.BeginReceive(myData, 0, myData.Length, SocketFlags.None,new AsyncCallback(ReceiveData), client);
ReceiveData方法的修改:
Socket client = (Socket)iar.AsyncState;
//获得该连接的数据接收缓冲区
byte[] mydata = RecvDataHash[client] as byte[];
string receivedData = _coder.GetEncodingString(mydata, recv);
//.....................消息处理//继续接收
client.BeginReceive(mydata, 0, mydata.Length, SocketFlags.None, new AsyncCallback(ReceiveData), client);
以上修改仅供参考。



































您还没有登录,请登录后继续操作。