TCPListener throwing Socket Exception on listener.EndAcceptTcpClient(asyncResult)

允我心安 提交于 2019-12-11 06:34:50

问题


I am working on a TCP Listener Service which waits for client to connect and receive files. The following code is used to initialize TCP Listener.

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

Then waiting for client as

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

This is the method 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
    }
}

It was working great when I tested on my local computer but after deployment, it started giving Socket Exception. The message by socket exception was as following. Even after catching exception, the same exception is constantly occurring. What is the cause of this exception and how can it be fixed?


回答1:


I'm not sure why it is problem, but i can see that you are using Sleep that will block the socket operations (I/O) and it could be the reason of your exception.

try this code, i tested before.

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);
        }
    }
}

I'm using your code to use to accept connections requests and read socket client in asynchronous ways, without use Sleeps.

  1. Start Socket Server and invoke an asynchronous method to accept connections (BeginListeningInBackground).
  2. Into BeginListeningInBackground the TCPClient socket is created (EndAcceptTcpClient) and start to read, in asynchronous way, check the method BeginToReadOnCLient(tcpClient);.
  3. After accept the the connections the TcpListener will be waiting for another connection: listener.BeginAcceptTcpClient(BeginListeningInBackground, listener);.

Into the method BeginToReadOnCLient the operation to read is asynchronous, usin the NetworkStream:

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

ReadFromClientStream has a sample logic to read the data, you must implement the correct logic to read the information according with the communication protocol.

IMPORTANT: Read about how to use these asynchronous operations in NetworkStream to avoid exception at the moment of: Stop TcpListener, close a client Connection, send or read information and how many bytes have been received/read.



来源:https://stackoverflow.com/questions/52966108/tcplistener-throwing-socket-exception-on-listener-endaccepttcpclientasyncresult

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!