c - 为什么我的服务器和客户端同时出现TIME_WAIT?

标签 c linux tcpclient tcpserver

我在测试我的服务器和客户端时遇到了一个奇怪的问题。 服务端和客户端同时出现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  

太奇怪了,我不知道为什么

最佳答案

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

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

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

也许你可以避免循环建立和关闭TCP连接,即改变你的服务器和客户端程序建立连接,然后进入循环交换数据。

关于c - 为什么我的服务器和客户端同时出现TIME_WAIT?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34057709/

相关文章:

java - Jmeter:TCP Sampler 错误:500 ReadException:从服务器读取错误,读取的字节数:0

c# - TCPClient 断开连接时显示消息

c - g_input_stream_read 中的 GTK+ 缓冲区

c++ - Linux 系统不允许创建套接字,因为 "Too many open files"*即使在重新启动后*

python - OpenCV 3 在 37% 时构建问题?

linux - Chrome Kiosk 模式会忽略缩放设置

c# - 为什么等待此任务 1022 毫秒工作正常,但 1023 毫秒会导致 AggregateException?

c++ - 什么是 c printf %f 默认精度?

c - 在 C99 中使用检查单元测试框架时出现语法错误

c - 如何知道 C 中数组中元素的确切数量?