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

C#客户端连接C++服务端停滞,连接C#服务端正常

问题分析与解决方案

你遇到的问题核心在于C++服务端的Socket处理逻辑存在严重错误,导致客户端连接后服务端无法正常处理请求,进而让C#客户端陷入停滞。

核心问题点:

  • 重复调用accept():服务端在第一次调用accept()获取到客户端连接后,没有处理这个连接,反而立刻再次调用accept(),这会让服务端阻塞在第二次accept()调用上,等待新的客户端连接,而已经连接的C#客户端的请求完全被忽略。
  • 缺少关键步骤的错误检查:bind()和listen()调用没有做错误判断,万一这两步失败,服务端也不会给出提示,可能隐藏潜在问题。
  • 连接后直接清理WSA资源:在第二次accept()后直接调用WSACleanup(),即使有客户端连接,也会立刻释放Socket资源,导致连接中断。
  • 无客户端数据交互逻辑:服务端完全没有编写接收客户端数据、返回响应的代码,C#客户端发送数据后一直在等待服务端回复,自然会停滞。

修正后的C++服务端代码

#include <winsock2.h>
#include <stdio.h>

#pragma comment(lib, "ws2_32.lib")

int main() {
    WSADATA wsaData;
    struct sockaddr_in address_of_server;
    struct sockaddr_in address_of_client;
    int size_of_address_of_client = sizeof(address_of_client);

    // 初始化WSA
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        printf("winsock initialization failure\n");
        return 1;
    }
    printf("winsock initialization success\n");

    // 创建服务端Socket
    SOCKET socket_of_server = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_of_server == INVALID_SOCKET) {
        printf("creating socket failure, error: %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    printf("creating socket success\n");

    // 配置服务端地址
    memset(&address_of_server, 0, sizeof(address_of_server));
    address_of_server.sin_family = AF_INET;
    address_of_server.sin_addr.s_addr = htonl(INADDR_ANY);
    address_of_server.sin_port = htons(8888);

    // 绑定Socket到地址
    if (bind(socket_of_server, (struct sockaddr*)&address_of_server, sizeof(address_of_server)) == SOCKET_ERROR) {
        printf("bind failed with error: %d\n", WSAGetLastError());
        closesocket(socket_of_server);
        WSACleanup();
        return 1;
    }
    printf("bind success\n");

    // 开始监听连接
    if (listen(socket_of_server, 5) == SOCKET_ERROR) {
        printf("listen failed with error: %d\n", WSAGetLastError());
        closesocket(socket_of_server);
        WSACleanup();
        return 1;
    }
    printf("listening on port 8888...\n");

    // 接受客户端连接(单客户端场景只需要一次调用)
    SOCKET clientSocket = accept(socket_of_server, (struct sockaddr*)&address_of_client, &size_of_address_of_client);
    if (clientSocket == INVALID_SOCKET) {
        printf("accept failed with error: %d\n", WSAGetLastError());
        closesocket(socket_of_server);
        WSACleanup();
        return 1;
    }
    printf("client connected from %s:%d\n", inet_ntoa(address_of_client.sin_addr), ntohs(address_of_client.sin_port));

    // 处理客户端数据交互
    char recvBuffer[1024] = {0};
    int recvBytes = recv(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
    if (recvBytes > 0) {
        printf("received data from client: %s\n", recvBuffer);

        // 准备返回给客户端的响应(对应C#客户端要读取的5个int)
        int responseData[5] = {100, 200, 300, 400, 500};
        send(clientSocket, (char*)responseData, sizeof(responseData), 0);
        printf("sent response to client\n");
    } else if (recvBytes == 0) {
        printf("client disconnected\n");
    } else {
        printf("recv failed with error: %d\n", WSAGetLastError());
    }

    // 按顺序清理资源
    closesocket(clientSocket);
    closesocket(socket_of_server);
    WSACleanup();

    return 0;
}

对C#客户端的优化建议

你的C#客户端在Data()方法中读取数据时,直接使用ReceiveBufferSize作为读取长度可能会导致问题,因为ReceiveBufferSize是Socket的缓冲区大小,不一定等于实际收到的数据长度。建议调整为:

void Data() {
    MainWindow mw = (MainWindow)Application.Current.MainWindow;
    NetworkStream serverStream = mw.clientSocket.GetStream();
    
    // 发送数据
    byte[] outStream = System.Text.Encoding.ASCII.GetBytes(A1G1.Text + "$");
    serverStream.Write(outStream, 0, outStream.Length);
    serverStream.Flush();
    
    // 读取响应:因为要读取5个int,直接分配对应大小的缓冲区
    byte[] inStream = new byte[sizeof(int) * 5]; 
    int bytesRead = serverStream.Read(inStream, 0, inStream.Length);
    if (bytesRead == sizeof(int)*5) {
        using (System.IO.MemoryStream ms = new System.IO.MemoryStream(inStream))
        using (System.IO.BinaryReader br = new System.IO.BinaryReader(ms)) {
            int[] inComingData = new int[5];
            for (int i = 0; i < 5; i++) {
                inComingData[i] = br.ReadInt32();
                Debug.WriteLine(inComingData[i].ToString());
                if (i == 0) {
                    A1G1Text.Text = inComingData[0].ToString();
                }
            }
        }
    } else {
        Debug.WriteLine("Received incomplete data from server");
    }
}

原代码卡住的根本原因

  1. C++服务端第一次accept()成功获取到C#客户端的连接后,没有处理这个连接,立刻又调用了第二次accept(),导致服务端一直等待第二个客户端连接,完全忽略了已经连接的第一个客户端。
  2. C#客户端成功连接后发送了数据,但服务端没有接收和处理,自然不会返回响应,最终让C#客户端卡在serverStream.Read()调用上,一直等待服务端的回复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:21:28