C# Tcp BeginAcceptTcpClient создает исключение ObjectDisposedException - PullRequest
0 голосов
/ 03 мая 2020

Я пытаюсь перейти с UDP на TCP, но я полностью потерян. : (

Это мой код сервера (не слишком длинный).

    private readonly TcpListener _tcpListener;

    public TCP(IPEndPoint endPoint)
    {
        try
        {
            _tcpListener = new TcpListener(endPoint);
            _tcpListener.Start();

            AcceptTcpClient();
            AcceptSocket();


            TestClient test = new TestClient();
            test.Connect();
        }
        catch (SocketException e)
        {
            Console.WriteLine("SocketException: " + e);
        }
        finally
        {
            _tcpListener.Stop();
        }
    }

    private void AcceptSocket()
    {
        _tcpListener.BeginAcceptSocket(AcceptIncomingSocket, _tcpListener);
    }
    private void AcceptTcpClient()
    {
        _tcpListener.BeginAcceptTcpClient(AcceptConnection, _tcpListener);
    }
    private void AcceptIncomingSocket(IAsyncResult ar)
    {
        try
        {
            var clientSocket = _tcpListener.EndAcceptSocket(ar);

            Console.WriteLine("Socket accepted: " + clientSocket.Connected);
        }
        catch (SocketException e)
        {
            Console.WriteLine("SocketException: " + e);
        }
    }

    private void AcceptConnection(IAsyncResult ar)
    {
        try
        {
            if (ar != null)
            {
                TcpClient client = _tcpListener?.EndAcceptTcpClient(ar);

                Console.WriteLine("Connected. " + (client != null && client.Connected));
                Console.ReadLine();
            }
        }
        catch (SocketException e)
        {
            Console.WriteLine("SocketException: " + e);
        }
        catch (ObjectDisposedException e)
        {
            Console.WriteLine("Disposed: " + e);
        }
    }

, а вот мой код клиента:

            client = new TcpClient();

            client.Connect("127.0.0.1", 2500);

            if (client.Connected)
            {
                Console.WriteLine("TestClient_Connected");
                Console.ReadLine();
            }

            NetworkStream stream = client.GetStream();

            byte[] toSend = System.Text.Encoding.ASCII.GetBytes("HELLO THERE");

            stream.Write(toSend, 0 , toSend.Length);

            byte[] toSend2 = System.Text.Encoding.ASCII.GetBytes("HELLO 2");

            stream.Write(toSend2, 0, toSend2.Length);


            Console.ReadLine();
        }
        catch (ArgumentNullException e)
        {
            Console.WriteLine("ArgumentNullException: {0}", e);
        }
        catch (SocketException e)
        {
            Console.WriteLine("SocketException: {0}", e);
        }

Проблема в том, когда я создать экземпляр клиента, мой сервер не будет вызывать AcceptConnection, но вместо этого он вызывает AcceptIncomingSocket. После этого, когда вторая запись клиента приходит в функцию, вызывается функция AcceptConnection и выдает это исключение: (Вывод всей консоли из-за сообщений отладки )

TestClient_Connected
Socket accepted: True


Disposed: System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.Socket'.
   at System.Net.Sockets.Socket.EndAccept(Byte[]& buffer, Int32& bytesTransferred, IAsyncResult asyncResult)
   at System.Net.Sockets.TcpListener.EndAcceptTcpClient(IAsyncResult asyncResult)
   at ChallengersDeepDedicated.Server.TCP.AcceptConnection(IAsyncResult ar) ```

1 Ответ

0 голосов
/ 04 мая 2020

Я бы порекомендовал вам взглянуть на документы Microsoft, есть хорошие примеры асинхронного сокет-клиента и сервера:

Сервер: https://docs.microsoft.com/en-us/dotnet/framework/network-programming/asynchronous-server-socket-example

Клиент: https://docs.microsoft.com/en-us/dotnet/framework/network-programming/asynchronous-client-socket-example

Написание программы сокет-клиент-сервер может быть сложным. Для хорошей реализации я бы порекомендовал вам погрузиться в детали и узнать, как это работает и как правильно его использовать.

Я уверен, что просмотр документации будет полезен и поможет вам понять концепцию сокетов.

Прочитав это, проверьте новую высокопроизводительную библиотеку System.IO.Pipeslines, которая управляет вашим буфером и облегчит вашу жизнь:

https://devblogs.microsoft.com/dotnet/system-io-pipelines-high-performance-io-in-net//#comment -5471

...