windows Winsock2和系统启动命令的奇怪之处

8yoxcaq7  于 2023-05-23  发布在  Windows
关注(0)|答案(1)|浏览(132)

有一个程序

#include <Winsock2.h>
#include <stdint.h>
#include <thread>

const uint16_t ANY_VALID_PORT = 12345;
SOCKET sock = INVALID_SOCKET;

void listenPort()
{
    sockaddr_in addr {};
    int addrSize = sizeof(addr);
    accept(sock, (SOCKADDR*)&addr, &addrSize);
}

// #define CORRECT_SEQUENCE

int main()
{
    WSADATA wsaData = { 0 };
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    sockaddr_in clientService {};
    clientService.sin_family = AF_INET;
    clientService.sin_port = htons(ANY_VALID_PORT);
    clientService.sin_addr.s_addr = INADDR_ANY;
    bind(sock, (SOCKADDR*)&clientService, sizeof(clientService));
    listen(sock, 2);

#ifdef CORRECT_SEQUENCE
    system("start cmd");
    std::thread listening { listenPort };
#else
    std::thread listening { listenPort };
    system("start cmd"); //could be virtually any program
#endif

    closesocket(sock);
    listening.join();

    WSACleanup();
}

预期行为:程序结束,而CMD继续在单独的窗口中运行。真实的行为:直到关闭新的cmd程序才结束。当CORRECT_SEQUENCE被定义时,它工作得很好。但是没有它,accept()即使sock关闭也不会返回。调试器告诉我们,我们在join()上遇到了困难。
这种依赖的原因是什么?cmd(甚至是空程序,只有while(1);总的来说,我和我们的港口没有什么关系。

n1bvdmb6

n1bvdmb61#

A socket handle created by the WSASocket or the socket function is inheritable by default.
system启动与CreateProcessAbInheritHandles = TRUE的进程。结果,sock被复制到子进程。
accept返回控制,当sock最后一个句柄关闭,但system("start cmd");之后cmd中存在另一个sock句柄。只有在你关闭cmd - accept返回错误(可能是WSAEINTR)之后
你的代码的两个变体都是错误的。两者都不起作用。您也可以在调用accept之前调用closesocket(sock);。所以一切都是错的
system("start cmd");在外部也不是有效的。此调用CreateProcessAcmd.exe 使用命令行 /c启动cmd -所以第一个cmd运行第二个cmd并退出..

  1. WSASocketWWSA_FLAG_NO_HANDLE_INHERIT一起使用,但不能使用socket
    1.永远不要使用system。使用CreateProcessW
    1.不调用cmd /c start cmd。如果您需要cmd -只需exec cmd
    1.不将句柄(sock)传递给另一个线程并并行关闭它

相关问题