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

10 篇文章 1 订阅

如题:

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()方法,是我目前觉得最稳定,可靠的;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值