"绑定:已经在使用的地址",即使设置了SO_REUSEADDR也是如此

lim*_*imp 5 c sockets bind

我写了一个简单的echo服务器,其中包括以下行:

int yes = 1;
if (setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
    perror("setsockopt");
    exit(1);
}
Run Code Online (Sandbox Code Playgroud)

尽管如此,当我尝试呼叫bind我最近使用的套接字时,我仍然会收到错误.事实上,如果我试图调用bind我在这个程序中使用的套接字,即使它不是最近的 - 就像它们没有被内核或其他东西清除一样,我会收到此错误.我还有别的办法吗?

这是完整的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>

void prepareHints(struct addrinfo *hints, int tcp_udp) {
    memset(hints, 0, sizeof(struct addrinfo));
    hints->ai_family = AF_UNSPEC;
    hints->ai_socktype = (tcp_udp == 1) ? SOCK_STREAM : SOCK_DGRAM;
    hints->ai_flags = AI_PASSIVE; /* autofill IP */
}

void writeSocket(int fd, const char *msg) {
    size_t nbytes = 0;
    size_t len = strlen(msg);
    while (nbytes < len)
        nbytes += send(fd, msg, len, 0);
}

void waitLoop(int sockfd) {
    int clientfd, nbytes;
    struct sockaddr addr;
    socklen_t len;
    char buf[512];
    while(1) {
        clientfd = accept(sockfd, &addr, &len);
        if (clientfd < 0) {
            perror("accept");
            exit(1);
        }
        while ((nbytes = recv(clientfd, buf, 512, 0)) != EOF) {
            buf[nbytes] = '\0';
            strcat(buf, "\r\n");
            writeSocket(clientfd, buf);
        }
        close(clientfd);
    }
}

int main(int argc, char **argv) {
    const char *port = (argc >= 2) ? argv[1] : "7474";
    struct addrinfo hints, *res;
    prepareHints(&hints, 1);

    int status = getaddrinfo(NULL, port, &hints, &res);
    if (status != 0) {
        printf("Error on getaddrinfo\n");
        exit(1);
    }

    /* scan through sockaddr's returned by getaddrinfo until we successfully set up a socket with one */
    int socketfd;
    struct addrinfo *cur;
    for (cur = res; cur != NULL; cur = cur->ai_next) {
        if ((socketfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) >= 0)
            break;
    }
    /* make sure we actually found one */
    if (socketfd == -1) {
        printf("Error on socket\n");
        exit(1);
    }
    /* bind the socket to the struct sockaddr_in contained in res */
    int bindres = bind(socketfd, cur->ai_addr, cur->ai_addrlen);
    if (bindres != 0) {
        perror("bind");
        exit(1);
    }

    int yes = 1;
    if (setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }

    if (listen(socketfd, 5) < 0) {
        printf("error on listen\n");
        exit(1);
    }

    printf("success, listening on socket %d, port %d\n", socketfd, ntohs(((struct sockaddr_in *)res->ai_addr)->sin_port));
    waitLoop(socketfd);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

小智 19

您在调用bind()后设置了SO_REUSEADDR.你需要在绑定之前设置它,而不是之后.