c# - TCPListener 在 listener.EndAcceptTcpClient(asyncResult) 上抛出 Socket 异常

标签 c# sockets tcpclient

我正在研究等待客户端连接和接收文件的 TCP 监听器服务。
以下代码用于初始化 TCP Listener。

    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 异常。套接字异常的消息如下。
enter image description here
即使在捕获异常之后,同样的异常也会不断发生。此异常的原因是什么,如何解决?

最佳答案

我不确定为什么会出现问题,但我可以看到您正在使用 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 .
  • 启动 Socket Server 并调用异步方法来接受连接 (BeginListeningInBackground)。
  • 进入BeginListeningInBackground TCPClient套接字已创建( EndAcceptTcpClient )并开始读取,以异步方式,检查方法 BeginToReadOnCLient(tcpClient); .
  • 接受连接后TcpListener将等待另一个连接:listener.BeginAcceptTcpClient(BeginListeningInBackground, listener); .

  • 进入方法BeginToReadOnCLient读取操作是异步的,使用 NetworkStream :
    NetworkStream ns = client.GetStream();
    bufferRx = new byte[10];
    ns.BeginRead(bufferRx, 0, 10, ReadFromClientStream, ns);
    
    ReadFromClientStream有一个示例逻辑来读取数据,您必须根据通信协议(protocol)实现正确的逻辑来读取信息。

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

    关于c# - TCPListener 在 listener.EndAcceptTcpClient(asyncResult) 上抛出 Socket 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52966108/

    相关文章:

    Java - socket.isConnected 使用端口 80 对任何 IP 地址返回 true

    Java多线程套接字客户端/服务器: sending and receiving Enummap objects

    c# - 显示小数点后 6 位小数

    c# - 窗口依赖注入(inject)

    c# - StackExchange.Redis - 是否可以确定端点的优先级?

    Java 客户端/服务器聊天室将消息作为对象发送

    c# - 当设备设置为每 30 秒锁定一次时,如何使 WP7 应用程序不进入锁定模式?

    C# 套接字和多线程

    C# 将两个 tcp 套接字连接在一起

    c# - .NET 相当于 recv?