TCPListener, генерирующий Исключение Гнезда на слушателе. EndAcceptTcpClient (asyncResult) - PullRequest
0 голосов
/ 24 октября 2018

Я работаю в службе прослушивания TCP, которая ожидает подключения клиента и получения файлов.Следующий код используется для инициализации прослушивателя TCP.

    var listener= new TcpListener(IPAddress.Any, port);
                    listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
listener.Start();

Затем ожидание клиента как

private void WaitForTcpClient(TcpListener listener){
    while(!listener.Pending()){
        Thread.Sleep(500);
    }
    listener.BeginAcceptTcpClient(BeginListeningInBackground, listener);
}

Это метод BeginListeningInBackground.

private async void BeginListeningInBackground(IAsyncResult asyncResult){
    var listener = asyncResult.AsyncState as TcpListener;
    var tcpClient = listener.EndAcceptTcpClient(asyncResult);
    Task.Run(() =>
            {
                WaitForTcpClient(listener);
            });
    using (NetworkStream netStream = tcpClient.GetStream()){
    //working with netStream here
    }
}

Это былоотлично работал, когда я тестировал на своем локальном компьютере, но после развертывания он начал выдавать Socket Exception.Сообщение по исключению сокета было следующим.enter image description here Даже после отлова исключения одно и то же исключение происходит постоянно.В чем причина этого исключения и как его можно исправить?

1 Ответ

0 голосов
/ 26 октября 2018

Я не уверен, почему это проблема, но я вижу, что вы используете Sleep, который блокирует операции сокета (I / O), и это может быть причиной вашего исключения.

попробуйте этот код, который я тестировал ранее.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Dummy
{
    public partial class Form1 : Form
    {
        TcpListener listener;
        byte[] bufferRx;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            int port = 9982;
            listener = new TcpListener(IPAddress.Any, port);
            listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
            listener.Start();

            //Begin to start the first connection
            System.Console.WriteLine("Waitting for client");
            listener.BeginAcceptTcpClient(BeginListeningInBackground, listener);
        }

        private void BeginListeningInBackground(IAsyncResult asyncResult)
        {
            System.Console.WriteLine("new for client request.");
            var listener = asyncResult.AsyncState as TcpListener;
            var tcpClient = listener.EndAcceptTcpClient(asyncResult);

            BeginToReadOnCLient(tcpClient);

            System.Console.WriteLine("Waitting for next client");
            listener.BeginAcceptTcpClient(BeginListeningInBackground, listener);

        }

        private void BeginToReadOnCLient(TcpClient client)
        {
            System.Console.WriteLine("Initi Rx on Client");

            NetworkStream ns = client.GetStream();
            bufferRx = new byte[10];
            ns.BeginRead(bufferRx, 0, 10, ReadFromClientStream, ns);// (BeginListeningInBackground, listener);
        }

        private void ReadFromClientStream(IAsyncResult asyncResult)
        {
            NetworkStream ns = (NetworkStream)asyncResult.AsyncState;
            System.Console.WriteLine("Read Data from client. DATA:[" + System.Text.Encoding.Default.GetString(bufferRx) + "]");
            bufferRx = new byte[10];
            ns.BeginRead(bufferRx, 0, 10, ReadFromClientStream, ns);
        }
    }
}

Я использую ваш код, чтобы использовать его для приема запросов на подключение и асинхронного чтения клиента сокета, без использования Sleeps.

  1. Запустите Socket Server и вызовите асинхронный метод для приема соединений (BeginListeningInBackground).
  2. В BeginListeningInBackground создан сокет TCPClient (EndAcceptTcpClient) и начните читать в асинхронном режиме, проверьте метод BeginToReadOnCLient(tcpClient);.
  3. После принятия соединений TcpListener будет ожидать другого соединения: listener.BeginAcceptTcpClient(BeginListeningInBackground, listener);.

В методе BeginToReadOnCLient операция чтения является асинхронной, используя NetworkStream:

NetworkStream ns = client.GetStream();
bufferRx = new byte[10];
ns.BeginRead(bufferRx, 0, 10, ReadFromClientStream, ns);

ReadFromClientStream имеет пример логики для чтенияdata , вы должны реализовать правильную логику для считывания информации в соответствии с протоколом связи.

ВАЖНО : прочитайте о том, как использовать эти асинхронные операции в NetworkStream, чтобы избежать исключенияв момент: остановите TcpListener, закройте клиентское соединение, отправьте или прочитайте информацию и сколько байтов было получено / прочитано.

...