ken
ken

Reputation: 1

Why my server and client appear TIME_WAIT at the same time?

I met a strange problem when I test my server and client. The server and client appear TIME_WAIT at the same time!

Here is my server code:

#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);
    }
}

And here is my client code:

#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);
 }

I run server and client on my machine. And the client cmd is

./client 127.0.0.1 9999 5 100 4000

and then I run

netstat -a | grep 9999 > log

when I run

grep -c TIME_WAIT log

the result is 501, but according to book, the result should be 500. I open the log, then I find server and client in TIME_WAIT at the same time on one connection

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

It is so strange, I don't know why

Upvotes: 0

Views: 1263

Answers (1)

Arun Kaushal
Arun Kaushal

Reputation: 631

You are establishing and closing connection between client and server in loop - client connects to server, sends some data, receives response from server and then closes the connection. Similarly the server also disconnects after this exchange. You are observing TIME_WAIT state as you are closing connections between client and server.

The TIME_WAIT state is a normal TCP connection state, as the TCP stack does not immediately wipe out the TCBs after FIN exchange. The TIME_WAIT state represents waiting for enough time to pass to be sure the remote TCP received the acknowledgment of its connection termination request. Please refer to TCP RFC 793 for more details on TCP state machine.

If you do a grep on port 9999, you will notice connection in ESTABLISHED state while your client and server are running.

Possibly you can avoid establishing and closing TCP connection in loop, that is, change your server and client programs to establish connection and then enter the loop for exchanging data.

Upvotes: 1

Related Questions