溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

一種C# TCP異步編程中遇到的問題

發布時間:2020-06-24 13:58:27 來源:網絡 閱讀:557 作者:胡壯壯 欄目:網絡安全

最近在維護公司的一個socket服務端工具,該工具主要是提供兩個socket server服務,對兩端連接的程序進行數據的透明轉發。

程序運行期間,遇到一個問題,程序的一端是GPRS設備,眾所周知,GPRS設備的網絡連接十分的不問題,由此會產生不少的“奇怪”問題。
實際過程中,程序運行幾個小時后,無線端的socket server斷開就再也無法打開。找了很久都沒發現。

通過wireshark抓取通信報文,一般是在TCP的三次握手時出的問題。
常規的TCP三次握手,由TCP的標識可簡單看作:SYN-SYN ACK-ACK,實際遇到問題時,標識為:SYN-RST ACK。

可以明顯看出,服務端發出了重置的標識,用來積極的拒絕了客戶端的連接。

程序的server部分代碼,采用的常規的TCP異步編程方式,一下是MSDN代碼

// This server waits for a connection and then uses asynchronous operations to
        // accept the connection with initial data sent from the client.

        // Establish the local endpoint for the socket.

        IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
        IPAddress ipAddress = ipHostInfo.AddressList[0];
        IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);        // Create a TCP/IP socket.
        Socket listener = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp );        // Bind the socket to the local endpoint, and listen for incoming connections.
        listener.Bind(localEndPoint);
        listener.Listen(100);        while (true) 
        {            // Set the event to nonsignaled state.
            allDone.Reset();            // Start an asynchronous socket to listen for connections and receive data from the client.
            Console.WriteLine("Waiting for a connection...");            // Accept the connection and receive the first 10 bytes of data. 
            // BeginAccept() creates the accepted socket.
            int receivedDataSize = 10;
            listener.BeginAccept(null, receivedDataSize, new AsyncCallback(AcceptReceiveDataCallback), listener);            // Wait until a connection is made and processed before continuing.
            allDone.WaitOne();
        }
    }    public static void AcceptReceiveDataCallback(IAsyncResult ar) 
    {        // Get the socket that handles the client request.
        Socket listener = (Socket) ar.AsyncState;        // End the operation and display the received data on the console.
        byte[] Buffer;        int bytesTransferred;
        Socket handler = listener.EndAccept(out Buffer, out bytesTransferred, ar);        //再次投遞接收,實現一直接收socket的操作
        listener.BeginAccept(null, receivedDataSize, new AsyncCallback(AcceptReceiveDataCallback), listener);
    }

經過問題的定位,可以判斷可能是程序的異步接收回調中出了問題,但實際添加調試信息后發現,在程序出現端口無法打開后,再進行回調函數操作,并無信息打出。
TCP異步編程,一般是成對的出現beginXXX...endXXX,再通過回調函數進行具體處理。

如下為accept的回調函數,代碼中使用了try..catch來捕獲異常,實際問題可能就出在這里,代碼如下:

 public static void AcceptReceiveDataCallback(IAsyncResult ar) 
    {        // Get the socket that handles the client request.
        Socket listener = (Socket) ar.AsyncState;        // End the operation and display the received data on the console.
        byte[] Buffer;        int bytesTransferred;        try{
            Socket handler = listener.EndAccept(out Buffer, out bytesTransferred, ar);
        }        catch(異常1 e){
            ...            return;
        }        catch(異常2 e){
            ...            return;
        }        //再次投遞接收,實現一直接收socket的操作
        listener.BeginAccept(null, receivedDataSize, new AsyncCallback(AcceptReceiveDataCallback), listener);
    }

程序在實際出現端口不能打開之前曾經進入過“異常1”/“異常2”,判斷很可能是程序進行了return,而無法再次投遞接收操作。
此時所有的端口打開操作,都會進入socket.listen(backlog)的隊列中,當accpet隊列中的內容無法通過完整begin..end操作取出,隊列滿后socket的底層協議棧則會拒絕新的socket連入。


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女