我正在制作一个并发的独立于平台的客户端-服务器程序,我的UNIXaccept()由于一个错误的文件描述符而失败,但Winsock运行良好.我在Linux和Windows上对其进行了测试.

int child, len, option = 1, rd;
SOCKET client_socket;
struct sockaddr_in client_addr;

SOCKET server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket == INVALID_SOCKET)
{
    fprintf(stderr, "Unable to initialize server socket");
    return -1;
}
else printf("Socket successfully created.\n");

if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(int)) == SOCKET_ERROR)
{
    fprintf(stderr, "setsockopt for SO_REUSEADDR failed.\n");
}
else printf("Set SO_REUSEADDR: ON\n");

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);

if (bind(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) == SOCKET_ERROR)
{
    fprintf(stderr, "Unable to bind to %s port %d\n", inet_ntoa(server_addr.sin_addr), PORT);
    perror("");
    close(server_socket);
    return -1;
}
else printf("Bind successful.\n");

if (listen(server_socket, SOMAXCONN) == SOCKET_ERROR)
{
    fprintf(stderr, "Unable to put server socket into listen state.\n");
    close(server_socket);
    return -1;
}
else printf("Listening on %s:%d.\n", inet_ntoa(server_addr.sin_addr), PORT);
socklen_t cli_addr_size = sizeof(client_addr);

while (true)
{
    //HERE
    client_socket = accept(server_socket, (struct sockaddr *) &client_addr, (socklen_t*) &cli_addr_size);
    if (client_socket == INVALID_SOCKET)
    {
        fprintf(stderr, "Accept failed with %d\n", client_socket);
        perror("");
        return -1;
    }
    else
    {
        printf("Client %s:%d joined the server.\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
        child = fork();
        if (child < 0)
        {
            perror("ERROR on fork");
            exit(-1);
        }
        printf("fork() returned %d.\n", child);
        if (child == 0)
        {
            close(server_socket);
            rd = recv(client_socket, rcvbuf, sizeof(rcvbuf), 0);
            if (rd < 0)
                perror("Error in receiving message");
            else if (rd == 0)
                printf("Client %s disconnected\n", inet_ntoa(client_addr.sin_addr));
            else
            {
                sprintf(sndbuf, "Client %s:%d: %s\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port),
                    rcvbuf);
                puts(sndbuf);
                if (send(client_socket, sndbuf, sizeof(sndbuf), 0) < 0)
                {
                    perror("Error in sending message");
                }
            }
        }
    }
}

I have included the chunk of code to prevent guesswork.
Is there also a better way to implement fork() for example by graceful prevention of orphans?
Improvements are welcome.

推荐答案

在第一次接受连接并派生子进程之后,子进程在完成处理连接后继续while (true).由于它关闭了侦听套接字,因此在调用accept时会出现错误.

完成处理后,子元素应该拨打_exit:

    if (child == 0)
    {
        close(server_socket);
        rd = recv(client_socket, rcvbuf, sizeof(rcvbuf), 0);
        if (rd < 0)
            perror("Error in receiving message");
        else if (rd == 0)
            printf("Client %s disconnected\n", inet_ntoa(client_addr.sin_addr));
        else
        {
            sprintf(sndbuf, "Client %s:%d: %s\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port),
                rcvbuf);
            puts(sndbuf);
            if (send(client_socket, sndbuf, sizeof(sndbuf), 0) < 0)
            {
                perror("Error in sending message");
            }
        }
        _exit(0);
    }

您可能还希望对子进程定期使用父进程wait,这样就不会有僵尸进程闲置. }

C++相关问答推荐

ARM上的Modulo Sim Aarch 64(NEON)

初始化char数组-用于初始化数组的字符串是否除了存储数组的位置之外单独存储在内存中

找出文件是否包含给定的文件签名

如果实际的syscall是CLONE(),那么为什么strace接受fork()呢?

我编译了一个新的c程序,并收到以下错误

为什么在4.9.37版的内核中,kfio还需要smp_wmb呢?

这是一个合法的C Strdup函数吗?

每个 struct 变量在C中都有自己的命名空间吗?

C-使用指针返回修改后的整数数组

判断X宏的空性

为什么将函数名括在括号中会禁用隐式声明?

等同于铁 rust 的纯C语言S未实现!()宏

当内存来自Malloc时,将char*转换为另一个指针类型是否违反了严格的别名规则?

正数之和是负数

在C++中允许使用字符作为宏参数

为什么电路板被循环删除?

为什么会导致分段故障?(C语言中的一个程序,统计文件中某个单词的出现次数)

这些表达式是否涉及 C 中定义的复合文字?

如何正确探测平台设备?

初始化动态分配的布尔二维数组的最佳方法是什么?