我已经编写了一个简单的回显服务器,它包含以下行:
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;
}
发布于 2013-05-05 04:46:40
您在调用bind()之后设置SO_REUSEADDR。您需要在绑定之前设置它,而不是在绑定之后。
发布于 2013-05-05 08:30:27
您在bind()
上收到一个错误,然后您将设置SO_REUSEADDR
。因此,它没有任何影响。
发布于 2013-05-05 05:36:33
简而言之,内核会保留它,因为在一段时间内,它不能确定它正在获得的数据包是给旧程序还是新程序的。等待总是最安全的。也就是说,我的理解是,在现代网络中,旧数据包立即延迟到达的可能性非常小。
简而言之,它是一个特性(至少以前是这样),而不是一个bug。
https://stackoverflow.com/questions/16378470
复制相似问题