Joaquín L. Robles
Joaquín L. Robles

Reputation: 6494

Server socket finishes when client closes connection

I'm trying to create a server socket with C++ in order to accept one client connection at a time. The program successfully creates the server socket and waits for incoming connections but when a connection is closed by the client the program would loop endlessly. Otherwise if the connection is interrupted it would keep waiting for new connections as expected. Any idea why this is happening? Thanks

This is my C++ server code:

   int listenfd, connfd, n;
   struct sockaddr_in servaddr, cliaddr;
   socklen_t clilen;
   pid_t     childpid;
   char mesg[1000];

   listenfd = socket(AF_INET, SOCK_STREAM, 0);

   bzero(&servaddr, sizeof(servaddr));
   servaddr.sin_family = AF_INET;
   servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
   servaddr.sin_port = htons(32000);
   bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

   listen(listenfd, 1024);

    while (true) {
        clilen = sizeof(cliaddr);
        connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);

        if ((childpid = fork()) == 0) {
            close (listenfd);

            while (true) {
                n = recvfrom(connfd, mesg, 1000, 0, (struct sockaddr *)&cliaddr, &clilen);
                sendto(connfd, mesg, n, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));

                mesg[n] = 0;
                printf("%d: %s \n", n, mesg);

                if (n <= 0) break;
            }
            close(connfd);
        }
    }

For some reason when the client closes the connection the program would keep printing -1: even with the if-break clause..

Upvotes: 1

Views: 1192

Answers (4)

Nil Null
Nil Null

Reputation: 414

The problem is your "n" and recvfrom. You are having a TCP client so the recvfrom won't return the correct value.

try to have a look on : How to send and receive data socket TCP (C/C++)

Edit 1 :

Upvotes: 1

Serge Ballesta
Serge Ballesta

Reputation: 148880

You never close connfd in parent process (when childpid != 0), and you do not properly terminate child process that will try to loop. Your if block should look like :

if ((childpid = fork()) == 0) {
    ...
    close(connfd);
    exit(0);
}
else {
    close(connfd);
}

But as you say you want to accept one connection at a time, you can simply not fork.

And as seen in other answers :

  • do not use mesg[n] without testing n >= 0
  • recvfrom and sendto are overkill for TCP simply use recv and send (or even read and write)

Upvotes: 2

macfij
macfij

Reputation: 3209

you've written a TCP server, but you use recvfrom and sendto which are specific for connection-less protocols (UDP).

try with recv and send. maybe that might help.

Upvotes: 0

Non-maskable Interrupt
Non-maskable Interrupt

Reputation: 3911

mesg[n] = 0;

This breaks when n<0, ie. socket closed

Upvotes: 1

Related Questions