4
votes

I'm new in socket programming under Linux (UNIX) sockets. I found the following code in the Internet, for a tcp-server that spawns a thread for each connection. However it doesn't work. the accept() function returns instantly, and doesn't wait for connection. What am I doing wrong ?

this is the code

int main(int argv, char *args[])
{
    struct sockaddr_in addr;
    int sd, port;

    port = htons(SERVER_PORT);

    /*--- create socket ---*/
    sd = socket(PF_INET, SOCK_STREAM, 0);
    if ( sd < 0 )
        panic("socket");

    /*--- bind port/address to socket ---*/
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = port;
    addr.sin_addr.s_addr = INADDR_ANY;                   /* any interface */
    if ( bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 )
        panic("bind");

    /*--- make into listener with 10 slots ---*/
    if ( listen(sd, 10) != 0 )
        panic("listen")

    /*--- begin waiting for connections ---*/
    else
    {   int sd;
        pthread_t child;
        FILE *fp;

        while (1)                         /* process all incoming clients */
        {
            sd = accept(sd, 0, 0);     /* accept connection */
            fp = fdopen(sd, "wr+");           /* convert into FILE* */
            pthread_create(&child, 0, servlet, fp);       /* start thread */
            pthread_detach(child);                      /* don't track it */
        }
    }
} 
5
You're not checking the return value of accept and then if it's -1 you're not checking errno - Jonathan Wakely
Ok, lesson learned, don't trust code you downloaded from a web-site. even examples fail often ! - stdcall
Fine, but just don't forget to choose the correct answer. - m0skit0
Besides the shadowing of sd, the call to accept() overwrites the listening socket descriptor. As this will work for one call to accept(), it surely won't work in a loop (as shown in the OP's code snippet). - alk

5 Answers

5
votes

You are shadowing the sd variable, passing an invalid socket to accept() which causes it to fail immediately.

It will likely return EBADF to signal a bad file descriptor. You would have noticed if you checked the return value in your code.

You should enable more compiler warnings, to catch things like these. With GCC you can use the -Wshadow option to enable such a warning.

2
votes

You're not checking the return value of accept() call. Most likely it's returning an error.

2
votes

there's a redefinition of sd variable

int sd;
0
votes

Some problems:

1) You are missing a comma on panic("listen")

2) You are declaring "sd" twice (one at main() one at else)

#include <stdio.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>

#define SERVER_PORT 30000

int main(int argv, char *args[])
{
    struct sockaddr_in addr;
    int sd, port;

    port = htons(SERVER_PORT);

    /*--- create socket ---*/
    sd = socket(PF_INET, SOCK_STREAM, 0);

    /*--- bind port/address to socket ---*/
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = port;
    addr.sin_addr.s_addr = INADDR_ANY;                   /* any interface */

    bind(sd, (struct sockaddr*)&addr, sizeof(addr));

    /*--- make into listener with 10 slots ---*/
    listen(sd, 10);

    /*--- begin waiting for connections ---*/
    pthread_t child;
    FILE *fp;

    while (1)                         /* process all incoming clients */
    {
        printf("before accept\n");
        sd = accept(sd, 0, 0);     /* accept connection */
        fp = fdopen(sd, "wr+");           /* convert into FILE* */
        //pthread_create(&child, 0, servlet, fp);       /* start thread */
        //pthread_detach(child);                      /* don't track it */
        printf("After accept\n");
    }

} 
0
votes

their is a redefinition of variable sd.

int sd; // at line 3 and 26