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

C#中如何停止并重新监听客户端Socket连接(ATM项目场景)

解决TCP/IP ATM服务器登出后重新监听客户端的问题

从你的描述来看,已经搞定了服务器启动监听、客户端登录建立连接的核心逻辑,现在需要处理客户端发送登出请求后断开当前连接并重启监听的需求。结合你提供的startlisten()方法,我们可以通过以下方式优化实现:

核心思路

  1. 服务器与客户端建立连接后,持续监听客户端消息,识别登出指令(比如约定的disconnect);
  2. 收到登出请求时,安全关闭当前客户端Socket及相关资源;
  3. 重启监听流程,等待下一个客户端的连接请求。

修改后的示例代码

// 把监听Socket声明为类级变量,方便在不同方法中操作和释放
private Socket _listenerSocket;
private byte[] _buffer = new byte[4000]; // 统一缓冲区,避免重复创建

public bool StartListen()
{
    try
    {
        // 初始化监听Socket(补充你的IP和端口配置)
        _listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        _listenerSocket.Bind(new IPEndPoint(IPAddress.Any, 12345)); // 替换为你的业务端口
        _listenerSocket.Listen(10);
        Console.WriteLine("服务器已启动,等待客户端连接...");

        // 用异步Accept避免阻塞主线程
        _listenerSocket.BeginAccept(OnClientConnected, _listenerSocket);
        return true;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"监听启动失败: {ex.Message}");
        return false;
    }
}

private void OnClientConnected(IAsyncResult ar)
{
    Socket listener = (Socket)ar.AsyncState;
    Socket clientSocket = listener.EndAccept(ar);
    Console.WriteLine($"客户端[{clientSocket.RemoteEndPoint}]已连接");

    // 开始异步接收客户端消息
    clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, OnClientMessageReceived, clientSocket);
}

private void OnClientMessageReceived(IAsyncResult ar)
{
    Socket clientSocket = (Socket)ar.AsyncState;
    try
    {
        int bytesRead = clientSocket.EndReceive(ar);
        if (bytesRead > 0)
        {
            string receivedMsg = Encoding.ASCII.GetString(_buffer, 0, bytesRead);
            Console.WriteLine($"收到客户端消息: {receivedMsg}");

            // 判断是否为登出请求(可根据你的业务约定修改指令)
            if (receivedMsg.Equals("disconnect", StringComparison.OrdinalIgnoreCase))
            {
                // 安全关闭客户端连接
                clientSocket.Shutdown(SocketShutdown.Both);
                clientSocket.Close();
                Console.WriteLine("客户端已登出,重新启动监听...");

                // 关闭原监听Socket并重启监听流程
                _listenerSocket.Close();
                StartListen();
                return;
            }

            // 这里处理其他ATM业务逻辑(比如查询、转账等)
            // ...

            // 继续监听客户端下一条消息
            clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, OnClientMessageReceived, clientSocket);
        }
        else
        {
            // 客户端主动断开连接
            clientSocket.Close();
            Console.WriteLine("客户端主动断开,重新启动监听...");
            _listenerSocket.Close();
            StartListen();
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"消息处理出错: {ex.Message}");
        clientSocket.Close();
        // 异常场景下也重启监听
        _listenerSocket.Close();
        StartListen();
    }
}

关键细节说明

  • 异步操作:用BeginAccept和BeginReceive实现异步监听/接收,避免同步代码阻塞主线程;
  • 资源释放:收到登出请求或连接异常时,必须调用Shutdown()和Close()释放Socket资源,防止端口被占用;
  • 监听重启:关闭旧的监听Socket后,重新调用StartListen()启动新一轮监听;
  • 指令约定:通过对比客户端发送的disconnect指令触发登出逻辑,你可以根据实际业务调整指令内容。

额外注意

  • 如果需要支持多客户端连接,需要维护一个客户端Socket列表,但ATM场景通常是单客户端连接,当前逻辑足够适用;
  • 可以根据需求添加更细致的日志记录、异常分类处理,提升代码的健壮性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:05:26