在 C 中使用信号量处理套接字

问题描述 投票:0回答:2

我有以下代码:

SOCKET sock = open_socket(szListenHost, iListenPort);

if (sock > 0) {
    SOCKET client;
    struct sockaddr_in peeraddr;
    T_socklen len = sizeof (struct sockaddr_in);

    char buf[1024];

    sin.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    sin.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    sin.hStdOutput =  GetStdHandle(STD_OUTPUT_HANDLE);
    sin.hStdError = GetStdHandle(STD_ERROR_HANDLE);
    sin.wShowWindow = SW_HIDE;
    dwCreationFlags = CREATE_NO_WINDOW;

    CreateProcess(NULL, buf, NULL, NULL, FALSE, dwCreationFlags, 
                  NULL, NULL, &sin, &pin);

    memset(&peeraddr, 0, sizeof (struct sockaddr_in));
    client = accept(sock, (sockaddr*)&peeraddr, &len);

    if (client > 0) {
        rv = message_loop(client);
    }
    closesocket(sock);
}

如您所见,这是出于询问原因打开 TCP 套接字。

情况如下:我的客户端应用程序(正在打开这些套接字的人)可能需要同时打开不同的 TCP 套接字,这可能会导致问题。

为了避免这些问题,我想询问一下套接字是否已经打开。如果是,则等待套接字再次释放,然后再次尝试打开套接字。

我知道信号量可以用于此目的,但我不知道如何做到这一点。

有人可以帮助我吗? 谢谢

首先我要感谢 John Bollinger 的快速回复。不幸的是,他们似乎存在误解:我并不是在寻找一种同时在不同时间打开一个套接字的方法,而是在寻找一种在套接字可用时被注意到的方法。事实上,我想做以下事情:而不是:

SOCKET sock = open_socket(szListenHost, iListenPort);

我可以做到这一点(非常基本上):

while (open_socket(szListenHost, iListenPort)) {sleep (1 second;)}

但这意味着我需要不断轮询套接字,从而产生相当大的开销。我听说信号量可以解决这个问题,比如:

SOCKET sock = handle_semaphore(open_socket(szListenHost, iListenPort));

“handle_semaphore”将是一个自动等待套接字被释放的系统,以便我的客户端进程可以立即打开套接字,而不会有被推到后面的风险。正如你所看到的,这都是谣言,但我不知道如何实现这一点。有谁知道信号量是否确实可以用于此目的,如果可能的话,请给我一些如何做到这一点的指导?

谢谢

c sockets semaphore
2个回答
1
投票

一旦打开,即使关闭套接字,也无法重新打开它。不过,您可以创建一个类似的新套接字。无论哪种方式,都很难可靠地确定先前打开的套接字是否已关闭,除非关闭它。

无论如何,通常的范例并不需要您所询问的那种协调机制。通常,一个进程的一个线程将打开套接字并负责接受其上的连接。如果希望程序能够一次处理多个连接,那么每次该线程接受一个新连接时,它都会将该连接分配给另一个线程或进程处理——通常但不一定是一个新创建的。

通常不需要或不需要打开新套接字来接收同一地址和端口上的其他连接。通常,您只需使用相同的套接字,而不关心已通过该套接字建立的任何连接的状态。也许,您可以使用信号量来协调同一进程的多个线程从同一套接字接收连接,但如果我是您,我会避免这种情况。


0
投票

同时情况发生了变化,我现在已经能够将信号量添加到我的套接字相关应用程序中。一般来说,这是可行的,但有时应用程序会挂起。

经过一些调试,我了解到应用程序在我启动以下 C 命令时挂起:

printf("Will it be accepted?\n");
fflush(stdout);
memset(&peeraddr, 0, sizeof (struct sockaddr_in));
client = accept(sock, (sockaddr*)&peeraddr, &len);
printf("It is accepted, the client is %d.\n",client);

=> 我可以在调试日志中看到“它会被接受吗?”,但我没有看到“它被接受,...”。

我承认我在测试时非常暴力(有时我停止调试会话而不让应用程序关闭套接字,...),但您可以想象客户以相同的方式行事,应用程序需要足够健壮。

有人知道如何避免“接受”命令进入这样的无限循环吗?

© www.soinside.com 2019 - 2024. All rights reserved.