c++ system()挂起使用netcat连接到不同线程中的套接字

标签 c++ multithreading sockets system freeze

我在一个单独的线程上启动一个简单的套接字服务器,并尝试在主线程上使用 netcat 连接到它。这是代码:

#include <cstdlib>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <iostream>
#include <string>
#include <cstring>

using namespace std;

void* callback(void*);

bool isServerReady = false;

int main()
{
    pthread_t thread;
    int result = pthread_create(&thread, 0, callback, 0);
    if (result != 0) {
        cout << "[ERROR] Unable to create thread" << endl;
    }

    while (!isServerReady) {
    }

    int returnValue = system("echo TEST | netcat localhost 1234");
    cout << "Return value: " << returnValue << endl;
    return 0;
}

void* callback(void* threadId)
{
    int serverSocketId = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocketId == -1) {
        cout << "[SERVER ERROR] Unable to create server socket." << endl;
        return (void*)-1;
    }

    int serverPort = 1234;
    struct sockaddr_in serverAddress;
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(serverPort);
    serverAddress.sin_addr.s_addr = INADDR_ANY;

    int bindReturn = bind(serverSocketId, (struct sockaddr*)&serverAddress, sizeof(serverAddress));
    if (bindReturn == -1) {
        cout << "[SERVER ERROR] Unable to bind server socket." << endl;
        return (void*) -1;
    }

    isServerReady = true;

    int waitQueueSize = 5;
    listen(serverSocketId, waitQueueSize);

    struct sockaddr_in clientAddress;
    socklen_t clientAddressSize = sizeof(clientAddress);
    int clientSocketId = accept(serverSocketId, (struct sockaddr*)&clientAddress, &clientAddressSize);
    if (clientSocketId == -1) {
        cout << "[SERVER ERROR] Unable to create client socket." << endl;
        return (void*)-1;
    }

    char clientBuffer[256];
    bzero(clientBuffer, 256);
    int charsRead = read(clientSocketId, clientBuffer, 255);
    if (charsRead == -1) {
        cout << "[SERVER ERROR] Unable to read client socket." << endl;
        return (void*)-1;
    }

    string serverMessage = "You wrote: ";
    serverMessage.append(clientBuffer);
    int charsWritten = write(clientSocketId, (char*)serverMessage.c_str(), (int)serverMessage.length());
    if (charsWritten == -1) {
        cout << "[SERVER ERRROR] Error writing to client socket." << endl;
        return (void*)-1;
    }

    int closeReturn = close(serverSocketId);
    if (closeReturn == -1) {
        cout << "[SERVER ERROR] Error closing server socket." << endl;
        return (void*)-1;
    }

    return (void*)0;
}

但是,system 函数永远不会返回,导致程序挂起:服务器的响应 “You wrote: TEST” 正确打印在控制台上,但之后程序只是挂起,没有到达打印返回值的行。如果我将相同的服务器代码提取到另一个程序中,启动它,并从命令行使用相同的 netcat 调用,我会得到相同的响应消息,然后 netcat 退出无需我做任何事情。

这是编译命令:

g++ -std=c++11 test.cpp -o test -lpthread && ./test

和编译器版本:

g++ (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4

为什么从 system() 内部调用时 netcat 没有返回?

最佳答案

感谢@kfsone,问题只是我的服务器从未关闭客户端套接字,从而阻止客户端 netcat 意识到服务器不再监听,并让它等待没有理由无限期。解决这个问题:

// ...
string serverMessage = "You wrote: ";
serverMessage.append(clientBuffer);
int charsWritten = write(clientSocketId, (char*)serverMessage.c_str(), (int)serverMessage.length());
if (charsWritten == -1) {
    cout << "[SERVER ERRROR] Error writing to client socket." << endl;
    return (void*)-1;
}

// ADDED THIS:
int closeClientReturn = close(clientSocketId);
if (closeClientReturn == -1) {
    cout << "[SERVER ERROR] Error closing client socket." << endl;
    return (void*)-1;
}

int closeReturn = close(serverSocketId);
if (closeReturn == -1) {
    cout << "[SERVER ERROR] Error closing server socket." << endl;
    return (void*)-1;
}

return (void*)0;

关于c++ system()挂起使用netcat连接到不同线程中的套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37243055/

相关文章:

c++ - 为什么在 CAS 循环失败时首选 std::memory_order_relaxed ?

linux - 未创建 TCP 监听套接字

c - SSL_read() 返回 0,SSL_get_error 返回 6。为什么在 SSL_read() 期间连接关闭?

c++ - 返回一个对象和作用域

c++ - 即使主窗口关闭,应用程序也不会退出

java - 如何阻塞和解除阻塞 servlet 线程?

ruby - 检查套接字客户端是否仍然连接

c++ - QGraphicsScene 中的鼠标移动跟踪

c++ - 什么使 C/C++ 程序成为 32/64 位?

android - 线程仅在 Android 的 Release模式下卡住 UI