2015-12-03 35 views
0

我在测试我的服务器和客户端时遇到了一个奇怪的问题。 服务器和客户端同时出现TIME_WAIT!为什么我的服务器和客户端同时出现TIME_WAIT?

这里是我的服务器代码:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <strings.h> //bzero 
#include <unistd.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <errno.h> 
#include <signal.h> 
#include <sys/types.h> 
#include <sys/wait.h> 

#define LISTEN_QUEUE 20 
#define MAX_LINE  1024 
#define MAXN   16384 

int parse(char *buf) 
{ 
    int num; 

    sscanf(buf, "%d", &num); 
    return num; 
} 

int main() 
{ 
    int listenfd, connfd, r, n; 
    pid_t childpid; 
    socklen_t chilen; 
    struct sockaddr_in chiaddr, servaddr; 
    char buf[MAX_LINE]; 
    char content[MAXN]; 

    listenfd = socket(AF_INET, SOCK_STREAM, 0); 
    if(listenfd < 0) 
     printf("listen socket get error\n"), exit(-1); 

    bzero(&servaddr, sizeof(servaddr)); 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    servaddr.sin_port = htons(9999); 

    r = bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); 
    if(r < 0) 
     printf("bind socket error\n"), exit(-1); 

    r = listen(listenfd, LISTEN_QUEUE); 

    memset(content, 'A', MAXN); 
    while(1) 
    { 
     chilen = sizeof(chiaddr); 
     connfd = accept(listenfd, (struct sockaddr *)&chiaddr, &chilen); 
     memset(buf, 0, MAX_LINE); 
     r = read(connfd, buf, MAX_LINE); 
     n = parse(buf); 
     write(connfd, content, n); 
     close(connfd); 
    } 
} 

这里是我的客户端代码:

#include <unp.h> 

#define MAXN 16384 

static int readn(int fd, char *buf, int nbytes) 
{ 
    int nread, ntoread, n; 

#ifdef __DEBUG__ 
    char temp[1024]; 
#endif /* __DEBUG__ */ 

    nread = 0; 
    ntoread = nbytes; 
    while(nread < nbytes) 
    { 
     n = read(fd, buf, ntoread); 
     if(n < 0) 
      printf("read nbytes error\n"), exit (-1); 
     else if(n == 0) 
      break; 
     else 
     { 

#ifdef __DEBUG__ 
      memcpy(temp, buf, n); 
      temp[n] = 0; 
      printf("%s\n", temp); 
#endif /* _DEBUG__ */ 

      buf += n; 
      nread += n; 
      ntoread = nbytes - nread; 
     } 
    } 
    return nread; 
} 

static int Tcp_connect(char *host, char *port) 
{ 
    struct hostent *h; 
    char str[16];  
    struct sockaddr_in addr; 

    h = gethostbyname(host); 
    addr.sin_family = h->h_addrtype; 
    addr.sin_port = htons(atoi(port)); 
    addr.sin_addr = *(struct in_addr *)(h->h_addr); 

#ifdef __DEBUG__ 
    if(h->h_addrtype == AF_INET) 
     printf("AF_INET\n"); 
    printf("server ip is :%s\n", inet_ntoa(addr.sin_addr)); 
#endif /* __DEBUG__ */ 

    int fd = socket(h->h_addrtype, SOCK_STREAM, 0); 
    if(fd < 0) 
     printf("socket get failed\n"), exit(-1); 

#ifdef __DEBUG__ 
    printf("socket get success\n"); 
#endif /* __DEBUG__ */ 

    if(connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) 
     printf("connect failed\n"), exit(-1); 

#ifdef __DEBUG__ 
    printf("connected success\n"); 
#endif /* __DEBUG__ */ 

    return fd; 
} 

int main(char argc, char *argv[]) 
{ 
    int i, j, fd, nchilds, nloops, nbytes; 
    pid_t pid; 
    ssize_t n, nread; 
    char request[MAX_LINE], reply[MAXN]; 

    if(argc != 6) 
     printf("usage : client <IP addr> <port> <#children> 
      <#loops/child> <#bytes/request>"), 
     exit(-1); 
    nchilds = atoi(argv[3]); 
    nloops = atoi(argv[4]); 
    nbytes = atoi(argv[5]); 
    snprintf(request, sizeof(request), "%d\n", nbytes); 

    for(i = 0; i < nchilds; i++) 
    { 
     if((pid = fork()) == 0) //son 
     { 
      nread = 0; 
      for(j = 0; j < nloops; j++) 
      { 
//    printf("begin connect\n"); 
       fd = Tcp_connect(argv[1], argv[2]); 
       write(fd, request, strlen(request)); 
       if((n = readn(fd, reply, nbytes)) != nbytes) 
        printf("server return %d bytes\n", (int)n), exit(-1); 
       else 
        nread += n; 
       close(fd); 
      } 
      printf("child %d done, read total %d bytes\n", i, (int)nread); 
      exit(0); 
     } 
    } 
    while(wait(NULL) > 0) ; 
    if(errno != ECHILD) 
     printf("wait error\n"), exit(-1); 
} 

我在我的机器上运行服务器和客户端。 而客户端cmd是

./client 127.0.0.1 9999 5 100 4000 

,然后我跑

netstat -a | grep 9999 > log 

当我运行

grep -c TIME_WAIT log 

结果是501,但根据book,结果应该是500。 我打开日志,然后在一个连接上同时在TIME_WAIT找到服务器和客户端

tcp  0  0 localhost:54915   localhost:9999   TIME_WAIT 
tcp  0  0 localhost:9999   localhost:54915   TIME_WAIT 

它就是这么奇怪,我不知道为什么

回答

1

您建立和关闭环路客户端和服务器之间的连接 - 客户端连接到服务器,发送一些数据,接收来自服务器,然后关闭响应连接。同样,服务器也在此交换后断开连接。当您关闭客户端和服务器之间的连接时,您正在观察TIME_WAIT状态。

TIME_WAIT状态是一个正常的TCP连接状态,因为TCP堆栈在FIN交换后不会立即清除TCB。 TIME_WAIT状态表示等待足够的时间以确保远程TCP收到其连接终止请求的确认。有关TCP状态机的更多详细信息,请参阅TCP RFC 793。

如果您在端口9999上执行grep,则在您的客户端和服务器正在运行时,您会注意到处于ESTABLISHED状态的连接。

可能您可以避免在循环中建立和关闭TCP连接,即更改您的服务器和客户端程序以建立连接,然后进入用于交换数据的循环。

+0

我知道一些关于TCP TIME_WAIT的知识。当我在我的服务器程序中调用close()时,我的服务器将FIN发送给客户端,服务器输入TIME_WAIT,但现在客户端也输入TIME_WAIT。我不知道为什么,并且我的服务器是迭代服务器,我认为将close()置于循环之外并不容易,谢谢 – ken

+0

这可能发生在同时关闭的情况下,在双方都调用close()之前从另一端接收FIN。在这种情况下,双方将以TIME_WAIT状态结束。这在你的客户端和服务器程序中是很有可能的,因为它们都运行在同一台机器上,并且可能会导致同时关闭。机器上的数据包捕获可能会有所帮助。 –

+0

哦,谢谢,我发现在TCPv1中同时关闭。 – ken

相关问题