您的位置:首页 > 编程语言 > C#

C# Socket在连接目标主机成功后的瞬间接、发操作必须要加锁;

2012-11-17 12:43 351 查看
如题:

C# Socket在连接目标主机成功后的瞬间接、发操作必须要加锁;

经过100~300次的调试次数,该问题,在Win7不会出现,在XP,100%出现,可能也是Socket调用系统底层,的问题,这时看的就是操作系统底层的一些稳定性了;

从而可以看到,Win7底层是比XP稳定的;

因为在Win7,C# Socket在连接目标主机成功后的瞬间接、发操作可以 不加锁操作;

而在Xp如果不加锁操作,则100%出现:

异常:

System.Net.Sockets.SocketException (0x80004005): 由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。

但在XP下,如果加断点调试的话,是100%不报上面这个异常,you know why?

类似这样的问题,很多都是因为异步操作过快,所以就在这些操作比较容易出现,异步问题加个锁操作即可;

private readonly object locker=new object();

public void BeginConnect()
{
//其它代码;
lock(locker)
{
//执行连接的代码体
}
//其它代码;
}

public void BeginSend()
{
//其它代码;
lock(locker)
{
//执行发送的代码体
}
//其它代码;
}

public void BeginRecieve()
{
//其它代码;
lock(locker)
{
//执行接收的代码体
}
//其它代码;
}


就有点像:原子操作一样;

还有别一种方法,Poll方法,可以参数官方MSDN说明:
http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.poll(v=vs.80).aspx
使用方法 :

private void BeginAsyncConnect(IAsyncResult ia)
{
lock (_receiveLocker)
{
try
{
Socket socket = ia.AsyncState as Socket;
while (!(_socket.Poll(1000 * 500, SelectMode.SelectWrite))) //当然这里你可以自己写个微秒的累加判断,到一定时间长度时就抛个超时异常
{
OnPoll(this, new ClientEvent(_socket, "Poll") { target = Interlocked.Add(ref _pollCount, 1) });
}
socket.EndConnect(ia);

if (Connected != null)
{
Connected(this, new ClientEvent(socket));
}
}
catch (Exception er)
{
Close("异步链接异常,断开链接,原因:\r\n" + er.ToString());
}
}
}


public void StartReceiverServer()
{
lock (_receiveLocker)
{
if (!_socket.Connected)
throw new Exception("_socket未链接无法执行StartServer");
while (!(_socket.Poll(1000 * 500, SelectMode.SelectWrite)))
{
OnPoll(this, new ClientEvent(_socket, "Poll") { target = Interlocked.Add(ref _pollCount, 1) });
}
_socket.BeginReceive(
_stateObject.BufferData, 0, ClientStateObj.BUFFERSIZE, SocketFlags.None,
new AsyncCallback(BeginAsyncReceive_PackageHeaderFixSize), _stateObject);
}
}


使用lock()+poll()方法,是我目前觉得最稳定,可靠的;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐