C ++ TCP服务器(Winsock)立即连接(无效客户端)然后关闭

C++ TCP Server (Winsock) Connecting (invalid client) Instantly Then Closes

编辑:研究解决方案 - 谷歌搜索 204.204.204.204 比更具描述性的请求更能让我走得更远。

老实说。束手无策。我不知道我怎么能花一整天时间做一些在 Flask(服务器)和 Javascript(客户端)中花费 10 分钟的事情。我需要在 C++ 中使用 运行 并允许客户端通过同一台机器上的 BlueStacks 端口进行连接。客户不重要,因为我什至无法做到这一点。

我试过 WinSocks,我试过 WxWidget 的网络实现,我什至试过一些随机的 C++ 包装器。所有这些都失败了(通常在示例中!就像在复制粘贴和到处都是错误一样)。所以我最终回到了 WinSockets 并按照 YouTube 上的教程进行操作。

int ServerStuff() {
WSADATA WsData;
WORD ver = MAKEWORD(2, 2);

int wsOK = WSAStartup(ver, &WsData);
if (wsOK != 0) {
    wxLogMessage("Can't initialize Winsock! Quitting");
    return false;
}

//Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET) {
    wxLogMessage("Can't create a socket! Quitting");
    return false;
}

//Bind the ip and port to a socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.S_un.S_addr = INADDR_ANY; //Could also use inet_pton

bind(listening, (sockaddr*)&hint, sizeof(hint));

//Tell winsock the socket is for listening
listen(listening, SOMAXCONN);

//Wait for a connection
sockaddr_in client;
int clientSize = sizeof(client);

SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
//if (clientSocket == INVALID_SOCKET) {
//  wxLogMessage("Client Invalid Socket");
//  return false;
//}

char host[NI_MAXHOST];  //Client's remote name
char service[NI_MAXHOST]; //Service (port) the client is connected on

ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXHOST);

if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0) {
    wxLogMessage("Can't initialize Winsock! Quitting");
}
else {
    inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
    wxLogMessage(host);
    int wut = client.sin_port;
    wxString mystring = wxString::Format(wxT("%i"), wut);
    wxLogMessage("Connected on port");
    wxLogMessage(mystring);
    //wxLogMessage(to_string(ntohs(client.sin_port)));
}
wxLogMessage("Got this far somehow");
//Close listening socket - we don't need it anymore - later on we'll learn how to accept multiple client
closesocket(listening);

//while loop: accept and echo message back to client
char buf[4096];

while (true)
{
    ZeroMemory(buf, 4096);

    //Wait for client to send data
    int bytesReceived = recv(clientSocket, buf, 4096, 0);

    if (bytesReceived == SOCKET_ERROR) {
        //wxLogMessage("ERROR in recv");
        break;
    }

    if (bytesReceived == 0) {
        wxLogMessage("Client Disconnected");
        break;
    }

    //Echo back to client
    send(clientSocket, buf, bytesReceived + 1, 0);

    //Close the socket
    closesocket(clientSocket);

    //Cleanup winsock
    WSACleanup();
    wxLogMessage("Welp");
}
}

// event handlers

void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close

ServerStuff();
//Close(true);
}

在 YouTube 视频上("Creating a TCP Server in C++" - 不允许 post 链接)这有效!命令 window 打开,无限空白,直到他连接到客户端,然后客户端发送一条消息,服务器在 return.

中回复完全相同的消息

不是我的。我的只是冲过一切然后关闭。我的日志过去常常立即退出注释代码,其中指出客户端套接字无效,所以我将其注释掉。现在我的输出是: 204.204.204.204 已连接端口 52428 不知何故走到这一步

我不知道该怎么办。我只是想通过同一台机器的 TCP 连接发送数据。我很困惑这怎么这么难。似乎一些随机进程正在立即尝试作为客户端连接到我的服务器?但是,当我明确托管在 54000 上时,为什么它允许连接到端口 52428?

我的目标: 启动服务器 使用 BlueStacks 中的 Java 应用程序连接到服务器 从服务器向客户端发送数据

将计算机作为服务器更有意义,因为会有多个 BlueStacks 实例,我宁愿不必 "spawn" 多个程序/服务器来完成我正在做的事情。

我看到你的套接字代码中有一些错误。

  • 如果 WSAStartup() 成功,则不调用 WSACleanup(),然后出现问题。

  • 如果 socket() 成功,则不调用 closesocket(),然后出现问题。

  • 没有将您传递给 bind()sockaddr_in 清零。结构中的随机字节可能导致 bind() 失败。

  • 忽略 bind()listen()accept()send() 的 return 值。

  • 没有正确处理 getnameinfo() 的 return 值。 return成功时为 0,失败时为 0。

  • 向客户端发回比您从客户端收到的字节多 1 个字节。如果客户端发送的字节数少于您的缓冲区可以容纳的字节数,那么由于您的 ZeroMemory() 调用,该额外字节将为 0x00。但是如果客户端实际上发送了足够的字节来完全填满你的缓冲区,那么你就会从你不拥有的内存中发送一个额外的字节。如果你真的想在你回显的所有内容之后发送一个空终止符,那么明确地这样做。否则,一个真正的回显服务器应该只返回它接收到的内容,不多也不少。

试试像这样的东西:

void ServerStuff() {
    WSADATA WsData;
    int ret = WSAStartup(MAKEWORD(2, 2), &WsData);
    if (ret != 0) {
        wxLogMessage("Can't initialize Winsock! Error: %d", ret);
        return;
    }

    //Create a socket
    SOCKET listening = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (listening == INVALID_SOCKET) {
        wxLogMessage("Can't create a socket! Error: %d", WSAGetLastError());
        WSACleanup();
        return;
    }

    //Bind the ip and port to a socket
    sockaddr_in hint = {};
    hint.sin_family = AF_INET;
    hint.sin_port = htons(54000);
    hint.sin_addr.s_addr = INADDR_ANY; //Could also use inet_pton

    ret = bind(listening, (sockaddr*)&hint, sizeof(hint));
    if (ret == SOCKET_ERROR) {
        wxLogMessage("Can't bind socket! Error: %d", WSAGetLastError());
        closesocket(listening);
        WSACleanup();
        return;
    }

    //Tell winsock the socket is for listening
    ret = listen(listening, SOMAXCONN);
    if (ret == SOCKET_ERROR) {
        wxLogMessage("Can't listen on socket! Error: %d", WSAGetLastError());
        closesocket(listening);
        WSACleanup();
        return;
    }

    //Wait for a connection
    sockaddr_in client = {};
    int clientSize = sizeof(client);

    SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
    if (clientSocket == INVALID_SOCKET) {
        wxLogMessage("Can't accept a client! Error: %d", WSAGetLastError());
        closesocket(listening);
        WSACleanup();
        return;
    }

    char host[NI_MAXHOST] = {};  //Client's remote name

    ret = getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, NULL, 0, 0);
    if (ret != 0) {
        wxLogMessage("Can't get client name info! Error: %d", ret);
        inet_ntop(AF_INET, &(client.sin_addr), host, NI_MAXHOST);
    }

    wxLogMessage("Client: %s, Connected on port: %hu", host, ntohs(client.sin_port));

    //Close listening socket - we don't need it anymore - later on we'll learn how to accept multiple client
    closesocket(listening);

    //while loop: accept and echo message back to client
    char buf[4096];
    int bytesReceived;

    while (true)
    {
        //Wait for client to send data
        bytesReceived = recv(clientSocket, buf, sizeof(buf), 0);

        if (bytesReceived == SOCKET_ERROR) {
            wxLogMessage("Can't read from client! Error: ", WSAGetLastError());
            break;
        }

        if (bytesReceived == 0) {
            wxLogMessage("Client Disconnected");
            break;
        }

        //Echo back to client
        ret = send(clientSocket, buf, bytesReceived, 0);
        if (ret == SOCKET_ERROR) {
            wxLogMessage("Can't send to client! Error: ", WSAGetLastError());
            break;
        }
    }

    //Close the socket
    closesocket(clientSocket);

    //Cleanup winsock
    WSACleanup();

    wxLogMessage("Welp");
}