在C#Winform中使用Socket.BeginConnect()连接服务器,并且IAsyncResult对象未返回错

本文关键字:并且 服务器 IAsyncResult 对象 返回 连接 C#Winform Socket BeginConnect | 更新日期: 2023-09-27 18:28:23

我正在做一个应用程序,它要求我作为客户端连接到服务器并从服务器接收数据。当连接断开时,我需要重新连接。以下是我的代码:

   public enum MySocketState
   {
       Disconnected = 0,
       Connecting,
       Connected
   }
    public Socket theDevSock = null;
    public MySocketState sockState = MySocketState.Disconnected;
    void DataProcess()
    {
        try
        {
            if (theDevSock == null || sockState == MySocketState.Disconnected)
            {
                Console.WriteLine("Trying to connect...");
                StartConnect();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }
    public bool StartConnect(/*AsyncCallback requestCallback*/)
    {
        Socket theSocket = null;
        try
        {
            Console.WriteLine("Start connect to server...");
            theSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            theSocket.BeginConnect("192.168.1.10", 1000, ConnectCallback, theSocket);
            sockState = MySocketState.Connecting;
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine("#### Unable to connect to server...");
        }
        CloseSocket();
        return false;
    }
    void ConnectCallback(IAsyncResult ar)
    {
        try
        {
            theDevSock = (Socket)ar.AsyncState;
            if (theDevSock != null)
            {
                if (theDevSock.Connected)
                {
                    sockState = MySocketState.Connected;
                    Console.WriteLine("Server is connected...");
                    theDevSock.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, this.ReceiveCallback, theDevSock);
                    return;
                }
            }
            Console.WriteLine("Failed to connect to server...");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
        CloseSocket();
    }
    private void ReceiveCallback(IAsyncResult AR)
    {
        try
        {
            if (theDevSock == null)
                theDevSock = (Socket)AR.AsyncState;
            int recieved = theDevSock.EndReceive(AR);  // Error occur in this line after re-connection.
            if (recieved <= 0)
            {
                CloseSocket();
                return;
            }
            byte[] recData = new byte[recieved];
            Buffer.BlockCopy(_recieveBuffer, 0, recData, 0, recieved);
            string strData = ASCIIEncoding.ASCII.GetString(recData);
            Console.WriteLine(strData);
            //Process the data stored in recData
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            CloseSocket();
        }
        finally
        {
            try
            {
                //Start receiving again
                if (theDevSock != null)
                    theDevSock.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, ReceiveCallback, theDevSock);
            }
            catch (Exception ex2)
            { }
        }
    }
    public void CloseSocket()
    {
        try
        {
            if (theDevSock != null)
            {
                if (theDevSock.Connected)
                    theDevSock.Shutdown(SocketShutdown.Both);
                theDevSock.Close();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
        theDevSock = null;
        sockState = MySocketState.Disconnected;
    }
    private void timer1_Tick(object sender, EventArgs e)
    {
        DataProcess();
    }
}

我使用计时器(timer1_tick)来检测服务器是否已连接。

如果连接已断开,则编码在重新连接回服务器时没有问题。问题是在重新连接之后,当它从服务器接收到第一个数据时,线路int recieved = theDevSock.EndReceive(AR)出现错误。错误消息如下:

A first chance exception of type 'System.ArgumentException' occurred in System.dll
A first chance exception of type 'System.ObjectDisposedException' occurred in System.dll
System.ArgumentException: The IAsyncResult object was not returned from the corresponding asynchronous method on this class.
Parameter name: asyncResult
at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult, SocketError& errorCode)
at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
at fform.ReceiveCallback(IAsyncResult AR) in c:'Work'Project 2015'Form1.cs:line 163
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.Socket'.
at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult, SocketError& errorCode)
at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
at fform.Form1.ReceiveCallback(IAsyncResult AR) in c:'Work'Project 2015'Form1.cs:line 163

为什么没有返回IAsyncResult对象?

在C#Winform中使用Socket.BeginConnect()连接服务器,并且IAsyncResult对象未返回错

根据MSDN

异步BeginConnect操作必须通过调用EndConnect方法。通常,该方法由requestCallback委托。

在中

void ConnectCallback(IAsyncResult ar)

在开始接收之前,您应该为EndConnect设置一行

void ConnectCallback(IAsyncResult ar)
{
    try
    {            
        theDevSock = (Socket)ar.AsyncState;
        theDevSock.EndConnect(ar);
        //blabla
    }
}

否则,连接并接收数据的套接字可能是不同的

注意:我不希望将调用BeginConnectSocket theSocket放在类范围内,而不是方法范围内,然后将其传递给theDevSock,因为它们最终是同一个套接字。