TCPListener在listener.EndAcceptTcpClient(asyncResult)上引发套接字异常

时间:2018-10-24 09:57:58

标签: c# sockets tcpclient

我正在研究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 :(得分:1)

我不确定为什么会出现问题,但是我可以看到您正在使用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套接字(TCPClientEndAcceptTcpClient套接字中,并开始以异步方式读取方法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 具有读取数据的示例逻辑,您必须实施正确的逻辑以根据通信协议读取信息。

重要:在以下情况下,了解如何在NetworkStream中使用这些异步操作来避免出现异常:停止TcpListener,关闭客户端连接,发送或读取信息以及多少字节已被接收/读取。