我编写了一个简单的回显服务器,其中包括以下行:
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;
}