C#Socket开发“网络连接超时设置Timeout”,解决网络连接速度过慢的问题

    技术2024-10-19  24

          近日,在进行PPC下的网络通讯程序开发时,当服务器的网络中断或连接异常时,客户端在进行TCP连接请求时“Socket.Connect()”速度明显过慢,通常20-30S才能有异常返回。.Net的System.Net.Sockets.TcpClient和System.Net.Sockets.Socket都没有直接为Connect/BeginConnect提供超时控制机制。因此,当服务器未处于监听状态,或者发生网络故障时,客户端连接请求会被迫等待很长一段时间,直到抛出异常。为解决这一问题,我查阅了部分资料同时进行了测试,现将解决方法整理如下:

         

    1、部分代码段:

    private ManualResetEvent connectDone = new ManualResetEvent(false);

     

    private void ConnectCallback(IAsyncResult ar) {    try     {        Socket client = (Socket) ar.AsyncState;        client.EndConnect(ar);            }     catch (Exception e)     {        OnErrorEvent(new ErrorEventArgs(e));    }    finally    {        connectDone.Set();    }}

     

     

            /// <summary>        /// 开始连接的方法        /// </summary>        /// <param name="ip"></param>        /// <param name="port"></param>        /// <param name="selfIP"></param>        /// <param name="selfPort"></param>        /// <returns></returns>        public bool ClientConnect(IPAddress ip, string port, string selfIP, string selfPort)        {            try            {                IPEndPoint remoteEP = new IPEndPoint(ip, Int32.Parse(port));网络端点表示为 IP 地址和端口号

                    //TCP连接                clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                    //开始连接

                    connectDone.Reset();                clientSocket.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), clientSocket);                connectDone.WaitOne(5000, false);//等待5秒

                    //连接成功                if (clientSocket.Connected)                {

                        //do something

                    }                return true;

                }            catch (Exception)            {

                    return false;            }        }

     

    这里,ManualResetEvent的WaitOne(TimeSpan, Boolean)起到了主要的作用。它将阻止当前线程,直到ManualResetEvent对象被Set或者超过timeout时间。上面的代码中,调用BeginConnect后通过WaitOne方法阻止当前线程,如果在timeoutMSec时间内连接成功,将在CallBackMethod回调中调用connectDone.Set,解除被阻塞的连接线程并返回。

     

    经过测试上面只是解决了连接速度慢的问题(网络异常时),设备可以在连接中断后自动重新连接服务器。但是,我发现当连接不正常时,clientSocket.BeginConnect得到的Socket的Connected属性仍为true,所以要想确保连接的可靠性只能采用信息交互的方式(即客户端向服务端发送要求反馈的信息,并能成功接收到反馈信息时才是正常的连接)。

    最新回复(0)