1

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..

Joaquín L. Robles
  • 6,261
  • 10
  • 66
  • 96
  • If 'n' is -1 you should call perror(), or use strerror[] in an error message, and you should *not* use it as an array index before testing it. – user207421 Aug 05 '14 at 03:52

4 Answers4

2

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)
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • thanks @Serge, removing the unnecesary fork, testing `n` before using it as index for `mesg` and using `recv` and `send` did solve the issue – Joaquín L. Robles Aug 04 '14 at 16:29
1
mesg[n] = 0;

This breaks when n<0, ie. socket closed

Non-maskable Interrupt
  • 3,841
  • 1
  • 19
  • 26
1

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 :

Community
  • 1
  • 1
Nil Null
  • 414
  • 5
  • 14
0

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.

macfij
  • 3,093
  • 1
  • 19
  • 24