You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BeginAccept未调用包含EndAccept的AcceptCallback函数问题求助

异步Socket服务端BeginAccept未触发回调的问题解决

你的代码存在几个核心逻辑错误,导致BeginAccept的回调无法正常工作,甚至整个服务端逻辑完全走不通:

  • 监听套接字的Connected属性判断错误:ServerSocket是负责监听连接请求的套接字,它本身永远不会处于Connected状态,所以while (!connected)里的判断永远不会成立,这个循环会无限执行,反复调用BeginAccept,既浪费CPU资源,也会让后续逻辑完全没有执行机会。
  • BeginAccept被重复调用:BeginAccept只需要调用一次就能启动连接监听,当有客户端发起连接时会自动触发回调,不需要放在循环里反复执行。如果需要接受多个客户端连接,应该在AcceptCallback回调结束后再次调用BeginAccept。
  • 错误使用监听套接字收发数据:监听套接字仅用于接受连接请求,实际和客户端通信的是EndAccept返回的Handler套接字,你后续用ServerSocket调用Receive和Send是完全错误的。

修正后的完整代码

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class Server
{
    // 用于和客户端通信的套接字
    private static Socket _clientSocket;

    public static void Main()
    {
        IPAddress serverAddress = IPAddress.Parse("127.0.0.1");
        int serverPort = 1234;

        Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        listenSocket.Bind(new IPEndPoint(serverAddress, serverPort));
        listenSocket.Listen(5);
        Console.WriteLine("Server is listening for connections");

        // 启动异步接受连接,仅需调用一次
        listenSocket.BeginAccept(AcceptCallback, listenSocket);

        // 保持主线程运行,避免程序直接退出
        Console.WriteLine("按任意键退出...");
        Console.ReadKey();

        // 清理资源
        _clientSocket?.Shutdown(SocketShutdown.Both);
        _clientSocket?.Close();
        listenSocket.Close();
    }

    private static void AcceptCallback(IAsyncResult ar)
    {
        Socket listenSocket = (Socket)ar.AsyncState;
        // 完成连接接受,获取与客户端通信的套接字
        _clientSocket = listenSocket.EndAccept(ar);
        Console.WriteLine("Client connected!");

        // 如果需要接受多个客户端连接,在此处再次调用BeginAccept
        // listenSocket.BeginAccept(AcceptCallback, listenSocket);

        // 启动异步接收客户端消息
        StartReceive();
    }

    private static void StartReceive()
    {
        byte[] buffer = new byte[1024];
        // 异步接收客户端数据
        _clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, buffer);
    }

    private static void ReceiveCallback(IAsyncResult ar)
    {
        byte[] buffer = (byte[])ar.AsyncState;
        try
        {
            int bytesRead = _clientSocket.EndReceive(ar);
            if (bytesRead <= 0)
            {
                Console.WriteLine("客户端断开连接");
                _clientSocket.Close();
                return;
            }

            string clientMessage = Encoding.ASCII.GetString(buffer, 0, bytesRead);
            Console.WriteLine("Recieved data from client: " + clientMessage);

            // 接收完成后继续监听下一条消息
            StartReceive();

            // 处理发送逻辑:读取控制台输入并发送给客户端
            Console.Write("输入要发送的消息:");
            string serverMessage = Console.ReadLine();
            if (!string.IsNullOrEmpty(serverMessage))
            {
                byte[] sendBuffer = Encoding.ASCII.GetBytes(serverMessage);
                _clientSocket.BeginSend(sendBuffer, 0, sendBuffer.Length, SocketFlags.None, SendCallback, null);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("接收数据出错:" + ex.Message);
            _clientSocket.Close();
        }
    }

    private static void SendCallback(IAsyncResult ar)
    {
        try
        {
            _clientSocket.EndSend(ar);
            Console.WriteLine("消息发送成功");
        }
        catch (Exception ex)
        {
            Console.WriteLine("发送数据出错:" + ex.Message);
            _clientSocket.Close();
        }
    }
}

关键修改说明

  1. 拆分套接字职责:将监听套接字listenSocket和通信套接字_clientSocket分离,前者负责监听连接,后者负责和客户端收发数据。
  2. 异步流程闭环:用BeginReceive和BeginSend实现非阻塞的收发逻辑,接收完成后再次调用StartReceive以持续监听客户端消息。
  3. 主线程保持存活:用Console.ReadKey()让主线程保持运行,避免服务端启动后直接退出。
  4. 资源清理:在程序退出时主动关闭套接字,释放系统资源。

内容的提问来源于stack exchange,提问作者Doblob83

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 03:26:07