这些天我一直在接近网络编程,我写了两个简单的例程来检查我是否正确。所以我在桌面上构建了服务器并启动它,然后我在笔记本电脑上构建了客户端并运行它,一切都按预期进行。当我第二次尝试运行它们时,服务器保持循环,两秒钟后客户端发出“连接错误!”。如果我在十五分钟后再试一次它会起作用,但我必须再等一下。我哪里错了?计算机都连接到我的LAN,79.13.199.165是我的调制解调器/路由器的IP,它将端口53124上的每个传入连接转发到桌面。在同一台PC上运行服务器和客户端时不会发生此问题。
server.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int main () {
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(53124);
sa.sin_addr.s_addr = htonl(INADDR_ANY);
memset(sa.sin_zero, '\0', sizeof(sa.sin_zero));
int mysocket = socket(PF_INET, SOCK_STREAM, 0);
bind(mysocket, (struct sockaddr*)&sa, sizeof(sa));
listen(mysocket, 5);
int inc;
struct sockaddr_in inc_addr;
socklen_t inc_addr_size = sizeof(inc_addr);
inc = accept(mysocket, (struct sockaddr*)&inc_addr, &inc_addr_size);
if (inc != -1) {
printf("accepting client\n");
}
send(inc, "ciao", sizeof("ciao"), 0);
close(inc);
return 0;
}
client.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int main () {
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(53124);
sa.sin_addr.s_addr = inet_addr("79.13.199.165");
memset(sa.sin_zero, '\0', sizeof(sa.sin_zero));
int mysocket = socket(PF_INET, SOCK_STREAM, 0);
if (mysocket == -1) {
printf("Could not create socket!\n");
}
if (connect(mysocket, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
printf("Error connecting!\n");
}
char message[5];
memset(message, '\0', sizeof(message));
recv(mysocket, message, 5, 0);
printf("%s\n", message);
return 0;
}
答案 0 :(得分:4)
当服务器关闭套接字时,会通过连接向后和向前发送一些ACK数据包。没有办法判断最后一个ACK是否成功传递,因此连接进入TIME_WAIT状态一段时间。这基本上使TCP堆栈等待任何丢失的数据包并将其丢弃。
通过使用SO_REUSEADDR设置setsockopt(),可以忽略这一点并立即重新使用套接字。后续连接可能会获得他们不应该获得的数据,但是对于您的小测试应用程序来说这不应该是一个问题。
修改强>
顺便说一下,你可能会对此感到困惑的一个原因是你没有对socket()bind()或listen()进行任何错误检查。 bind()调用肯定会返回错误并在Linux上设置errno,EINVAL。