简单的服务器/客户端C网络练习

问题描述:

这些天我一直在接近网络编程,我写了两个简单的例程来检查我是否正确。所以我在桌面上构建了服务器并启动了它,然后我在笔记本电脑上构建了客户端,然后运行它,并且一切都按预期进行。当我第二次尝试运行它们时,服务器不断循环,两秒钟后客户端发出“错误连接!”。如果我在15分钟后再试一次,那么它就可以工作,但是我必须再等一等。我错在哪里?计算机都连接到我的LAN,79.13.199.165是我的调制解调器/路由器的IP,它将端口53124上的每个传入连接转发到桌面。在同一台PC上运行服务器和客户端时,不会发生此问题。简单的服务器/客户端C网络练习

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; 
} 
+1

当两台计算机位于局域网上时,您的路由器可能不会转换端口。尝试使用专用地址进行连接(即,如果使用NAT) – Tibor 2012-04-16 13:12:02

+3

执行Google搜索“TCP TIME_WAIT”和“setsockopt SO_REUSEADDR”。 – 2012-04-16 13:16:08

+0

那么,如果我不得不接受来自我刚刚在四分钟内退出的客户端的新连接?我应该更好地减少'TIME_WAIT'还是让客户端迭代一系列端口? – 2012-04-16 13:43:18

当服务器关闭套接字,一对夫妇ACK数据包获取向后和向前跨发送的连接。无法判断最后一个ACK是否成功传送,因此连接进入TIME_WAIT状态一段时间。这基本上给了TCP堆栈时间来等待丢失的数据包并将其丢弃。

可以忽略这一点,并通过使用setsockopt()来设置SO_REUSEADDR而立即重新使用套接字。后续连接可能会获得它们不应该使用的数据,但对于您的小测试应用程序而言,这应该不成问题。

编辑

顺便说一句,一个原因,你很可能得到这个困惑的是,你没有做任何错误校验插座()的bind()或听()。 bind()调用肯定会返回一个错误,并在Linux上设置errno,EINVAL。

+0

这不是客户的问题吗? – 2012-04-16 13:48:34

+0

@格莱德:不,客户端套接字端口是随机选择的。它是绑定到特定端口号的服务器端套接字,这是问题所在。 – JeremyP 2012-04-16 13:54:10