Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C &引用;绑定:地址已在使用中“;即使有这么一套_C_Sockets_Bind - Fatal编程技术网

C &引用;绑定:地址已在使用中“;即使有这么一套

C &引用;绑定:地址已在使用中“;即使有这么一套,c,sockets,bind,C,Sockets,Bind,我编写了一个简单的echo服务器,其中包括以下内容: int yes = 1; if (setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); exit(1); } 然而,尽管如此,当我尝试在最近使用的套接字上调用bind时,仍然会遇到一个错误。事实上,如果我试图在我在这个程序中使用的套接字上调用bind,我会遇到这个错误,即使它不是

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

int yes = 1;
if (setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
    perror("setsockopt");
    exit(1);
}
然而,尽管如此,当我尝试在最近使用的套接字上调用
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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
void prepareHints(结构addrinfo*提示,int-tcp\u-udp){
memset(提示,0,sizeof(struct addrinfo));
提示->ai_family=AF_unsec;
提示->ai_socktype=(tcp_udp==1)?SOCK_流:SOCK_DGRAM;
提示->ai_标志=ai_被动;/*自动填充IP*/
}
void writeSocket(int-fd,const-char*msg){
大小字节=0;
尺寸长度=strlen(msg);
while(n字节=2)?argv[1]:“7474”;
结构addrinfo提示,*res;
准备提示(和提示,1);
int status=getaddrinfo(NULL、端口、提示和res);
如果(状态!=0){
printf(“getaddrinfo上的错误\n”);
出口(1);
}
/*扫描getaddrinfo返回的sockaddr,直到我们成功地用一个socket设置了一个sockaddr*/
int socketfd;
结构addrinfo*cur;
for(cur=res;cur!=NULL;cur=cur->ai_next){
如果((socketfd=socket(res->ai_系列,res->ai_socktype,res->ai_协议))>=0)
打破
}
/*确保我们真的找到了*/
如果(socketfd==-1){
printf(“套接字错误\n”);
出口(1);
}
/*将套接字绑定到res中包含的结构sockaddr_*/
int bindres=bind(socketfd,cur->ai_addr,cur->ai_addrlen);
if(bindres!=0){
佩罗(“绑定”);
出口(1);
}
int yes=1;
if(setsockopt(socketfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int))=-1){
perror(“setsockopt”);
出口(1);
}
如果(监听(socketfd,5)<0){
printf(“侦听时出错\n”);
出口(1);
}
printf(“成功,侦听套接字%d,端口%d\n”,socketfd,ntohs(((struct sockaddr_in*)res->ai_addr)->sin_端口));
waitLoop(socketfd);
返回0;
}

您正在设置在调用bind()后重新使用eaddr。您需要在绑定之前设置它,而不是在绑定之后。

简短的版本是内核保留它,因为在一段时间内,它无法判断它获取的数据包是用于旧程序还是新程序。等待总是最安全的。也就是说,我的理解是,在现代网络中,旧数据包迟到一分钟的可能性非常小


真正简短的版本是,它是一个功能(至少过去是)而不是一个bug。

您在
bind()
上遇到了一个错误,您正在设置
,因此\u REUSEADDR
之后。因此它没有任何效果。

netstat
(或等效)显示..?非常感谢!没错。更正:旧数据包意外迟到一分钟的可能性相当小。由于恶意(包括针对其他人的恶意的副作用)导致数据包延迟一分钟的可能性很大。这并不是真正的纠正——有人试图攻击你的可能性很小。但这是一个很好的澄清:)无论如何,重点是这是一件好事,你不应该反对它,除非是在开发中,即使它可能永远不会咬你。这并不能回答关于问题设置的问题,所以_REUSEADDR选项,而不是为什么内核在程序结束后保持打开端口(OP知道这一点)。