Error in accept() system call

Error in accept() system call

Post by Santosh Golec » Thu, 14 Aug 2003 11:54:52



Hello,

I am using Linux 2.4.18 kernel to do some simple network programming.
I wrote a simple TCP client/server example which is shown below. My
problem is that when the client tries to connect to the server, I get
an error:

  Error 22
  Invalid Argument

I get this error when the server accepts connection from the client
i.e in the accept() system call.

When I try the same example but with a UDP server( Datagram socket and
no accept system call) and a client it works. I dont know why I keep
getting this error. I would appreciate any help on this.

Code Listing
------------

server.c

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>

int main(int argc, char *argv[]){

        int sockfd, nsockfd;
        struct sockaddr_in servaddr, cliaddr;
        int m,n;
        socklen_t len, clilen;
        char msg[1000];

        sockfd = socket(AF_INET, SOCK_STREAM, 0);

        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = inet_addr(argv[1]);
        servaddr.sin_port = htons(32000);

        /* Bind the socket and check for errors  */
        if(bind(sockfd , (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0
)
        {
          printf("Error binding Server Socket: ErrorNo:%d\n",errno);
          perror("Meaning :");
          exit(1);
        }

        /* Listen at the particular socket */
        if(listen(sockfd ,5) < 0 )
        {
          printf("Error listening  Server Socket. ErrorNo: %d\n",errno);
          perror("Meaning :");
          exit(1);
        }

        for( ; ;) {
// Error occurs here            
         if(( nsockfd = accept(sockfd ,(struct sockaddr *) &cliaddr ,
&clilen) ) < 0 )
        {
          printf("Error accepting connection. ErrorNo: %d\n",errno);
          perror("Meaning :");
          close(sockfd);
          exit(1);
        }
        else
        {
          m = read(sockfd, msg, 1000);
          n = write(sockfd, msg, 1000);
          printf("-------------------------------------\n");
          msg[m] = '\0';
          printf("Received the following message\n");
          printf("%s", msg);
          close(nsockfd);
        }
        }

        close(sockfd);
        return 0;

Quote:}

client.c
--------

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>

int main(int argc, char *argv[]){

        int sockfd;
        struct sockaddr_in servaddr, cliaddr;
        int m,n;
        char sendline[1000];
        char recvline[1000];

        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = inet_addr(argv[1]);
        servaddr.sin_port = htons(32000);

        sockfd = socket(AF_INET, SOCK_STREAM, 0);

        if(connect(sockfd,(struct sockaddr *) &servaddr ,sizeof(struct
sockaddr)) < 0)
        {
          printf("Error Connecting to server. ErrorNo: %d",errno);
          perror("Meaning :");
          close(sockfd);
          exit(1);
        }

        while(fgets(sendline, 1000, stdin) != NULL){

           m = write(sockfd, sendline, 1000);
           n = recvfrom(sockfd, recvline,1000, 0 , NULL, NULL);
           recvline[n] = '\0';

           printf("-----------------------------------------\n");
           printf("Message received from server\n");
           fputs(recvline, stdout);
        }

        close(sockfd);
        return 0;

Quote:}

 
 
 

Error in accept() system call

Post by Chris Fowle » Thu, 14 Aug 2003 12:17:08


In the server code you need to read and write to nsockfd.  This
is the fd that was given to you by accept().  Make sure you also
close nsokffd when complete.  

> Hello,

> I am using Linux 2.4.18 kernel to do some simple network programming.
> I wrote a simple TCP client/server example which is shown below. My
> problem is that when the client tries to connect to the server, I get
> an error:

>   Error 22
>   Invalid Argument

> I get this error when the server accepts connection from the client
> i.e in the accept() system call.

> When I try the same example but with a UDP server( Datagram socket and
> no accept system call) and a client it works. I dont know why I keep
> getting this error. I would appreciate any help on this.

> Code Listing
> ------------

> server.c

> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <stdio.h>
> #include <errno.h>

> int main(int argc, char *argv[]){

>         int sockfd, nsockfd;
>         struct sockaddr_in servaddr, cliaddr;
>         int m,n;
>         socklen_t len, clilen;
>         char msg[1000];

>         sockfd = socket(AF_INET, SOCK_STREAM, 0);

>         bzero(&servaddr, sizeof(servaddr));
>         servaddr.sin_family = AF_INET;
>         servaddr.sin_addr.s_addr = inet_addr(argv[1]);
>         servaddr.sin_port = htons(32000);

> /* Bind the socket and check for errors  */
> if(bind(sockfd , (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0
> )
> {
> printf("Error binding Server Socket: ErrorNo:%d\n",errno);
> perror("Meaning :");
> exit(1);
> }

> /* Listen at the particular socket */
> if(listen(sockfd ,5) < 0 )
> {
> printf("Error listening  Server Socket. ErrorNo: %d\n",errno);
> perror("Meaning :");
> exit(1);
> }

> for( ; ;) {
> // Error occurs here
> if(( nsockfd = accept(sockfd ,(struct sockaddr *) &cliaddr ,
> &clilen) ) < 0 )
> {
> printf("Error accepting connection. ErrorNo: %d\n",errno);
> perror("Meaning :");
>           close(sockfd);
> exit(1);
> }
> else
> {
> m = read(sockfd, msg, 1000);
>           n = write(sockfd, msg, 1000);
>           printf("-------------------------------------\n");
> msg[m] = '\0';
> printf("Received the following message\n");
> printf("%s", msg);
> close(nsockfd);
> }
>         }

>         close(sockfd);
>         return 0;
> }

> client.c
> --------

> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <stdio.h>
> #include <errno.h>

> int main(int argc, char *argv[]){

>         int sockfd;
>         struct sockaddr_in servaddr, cliaddr;
>         int m,n;
>         char sendline[1000];
>         char recvline[1000];

>         bzero(&servaddr, sizeof(servaddr));
>         servaddr.sin_family = AF_INET;
>         servaddr.sin_addr.s_addr = inet_addr(argv[1]);
>         servaddr.sin_port = htons(32000);

>         sockfd = socket(AF_INET, SOCK_STREAM, 0);

> if(connect(sockfd,(struct sockaddr *) &servaddr ,sizeof(struct
> sockaddr)) < 0)
> {
> printf("Error Connecting to server. ErrorNo: %d",errno);
> perror("Meaning :");
>           close(sockfd);
>           exit(1);
> }

>         while(fgets(sendline, 1000, stdin) != NULL){

> m = write(sockfd, sendline, 1000);
> n = recvfrom(sockfd, recvline,1000, 0 , NULL, NULL);
>            recvline[n] = '\0';

> printf("-----------------------------------------\n");
> printf("Message received from server\n");
> fputs(recvline, stdout);
>         }

> close(sockfd);
>         return 0;
> }


 
 
 

Error in accept() system call

Post by beltor » Thu, 14 Aug 2003 16:02:47



> Hello,

> // Error occurs here              
>     if(( nsockfd = accept(sockfd ,(struct sockaddr *) &cliaddr ,
> &clilen) ) < 0 )
>    {
>      printf("Error accepting connection. ErrorNo: %d\n",errno);
>      perror("Meaning :");
>           close(sockfd);
>      exit(1);
>    }
>    else
>    {

Actually, you are wrong.  Your error occurs here.

Quote:>      m = read(sockfd, msg, 1000);
>           n = write(sockfd, msg, 1000);
>           printf("-------------------------------------\n");
>      msg[m] = '\0';
>      printf("Received the following message\n");
>      printf("%s", msg);
>      close(nsockfd);
>    }
>         }

>         close(sockfd);
>         return 0;
> }

According to the man page for accept, it returns a new fd for the
connected socket (which you assigned to 'nsockfd'), but leaves the
original in the listen state; so you are trying to read from & write
to a 'listening' and not 'connected' socket.  Change your reads and
writes.

Also, your procedure for printing errors lacks; perror() uses the
extern int errno for it's error messages; some library functions
(printf()) overwrite that number even if the overall function was a
success.... you are getting the wrong error messages.  do:
----
extern int errno;
int errnum;
main() { etc etc
----

and then replace each of your error reporting functions with something
like:
----
if( this() < 0 ) {
  errnum = errno;
  perror("Error doing this");
  fprintf(stdout, "Error Number %d\n", errnum);
  exit(EXIT_FAIL);

Quote:}

----
Make a wrapper (perr( char* ) { ... }) for it; save some typing.

That should help you track down the errors a little better.  I keep
getting a broken pipe.  Don't forget to surround your read()s and
write()s (and maybe close()s, sometimes a write error won't be caught
until the fd is closed IIRC).

Also, look into strerror_r() which will fill a string buffer with the
error message, since perror() and strerror() are not threadsafe (if
two threads try to report different errors, one will clobber the
other).

Hope that helps.

-t.

 
 
 

Error in accept() system call

Post by Villy Kru » Thu, 14 Aug 2003 16:32:57


On 13 Aug 2003 00:02:47 -0700,

Quote:>extern int errno;

Carefull,  these days errno is often a macro which calls a function returning
a pointer to an int and the macro then dereference this macro so it appears to
work like a variable called errno.

Quote:>int errnum;
>main() { etc etc

Example from GNU glibc2:

/usr/include/bits/errno.h:#define errno (*__errno_location ())

This is necessary for supporting threaded code.

The proper way to define errno is to #include <errno.h>

Villy

 
 
 

Error in accept() system call

Post by Santosh Golec » Fri, 15 Aug 2003 10:44:17


Hi all,

Alright, I made all the changes as recommended by all the people.
For time being I am ignoring the perror and just printing the errno.
I still get the same error at the accept system call.

The sequence of steps that I perform to start the server and the
client are
---
./client 127.0.0.1
---
./server 127.0.0.1
Error accepting connection. ErrorNo: 22    // This is the error
message
---

I am pretty sure the error is not the read or write sytem call. It is
in accept only but I am sure what mistake I am doing. This is the
first time I have encountered this problem.

Thanks
Santosh

The code is shown below:

client.c
--------

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>

extern int errno;

int main(int argc, char *argv[]){
        int errnum;
        int sockfd;
        struct sockaddr_in servaddr, cliaddr;
        int m,n;
        char sendline[1000];
        char recvline[1000];

        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = inet_addr(argv[1]);
        servaddr.sin_port = htons(32000);

        sockfd = socket(AF_INET, SOCK_STREAM, 0);

        if(connect(sockfd,(struct sockaddr *) &servaddr ,sizeof(struct
sockaddr)) < 0)
        {
          errnum = errno;
          printf("Error Connecting to server. ErrorNo: %d",errum);
          exit(1);
        }

        while(fgets(sendline, 1000, stdin) != NULL){

           m = write(sockfd, sendline, 1000);
           n = recvfrom(sockfd, recvline,1000, 0 , NULL, NULL);
           recvline[n] = '\0';

           printf("-----------------------------------------\n");
           printf("Message received from server\n");
           fputs(recvline, stdout);
        }

        close(sockfd);
        return 0;

Quote:}

-------------------------

server.c
--------

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>

extern int errno;

int main(int argc, char *argv[]){

        int errnum;
        int sockfd, nsockfd;
        struct sockaddr_in servaddr, cliaddr;
        int m,n;
        socklen_t len, clilen;
        char msg[1000];

        sockfd = socket(AF_INET, SOCK_STREAM, 0);

        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = inet_addr(argv[1]);
        servaddr.sin_port = htons(32000);

        //        bind(sockfd, (struct sockaddr *)&servaddr,
sizeof(servaddr));
          /* Bind the socket and check for errors  */
        if(bind(sockfd , (struct sockaddr *) &servaddr,
sizeof(servaddr)) < 0 )
        {
          errnum = errno;
          printf("Error binding Server Socket: ErrorNo:%d\n",errnum);
          //perror("Meaning :");
          exit(1);
        }

        /* Listen at the particular socket */
        if(listen(sockfd ,5) < 0 )
        {
          errnum = errno;
          printf("Error listening  Server Socket. ErrorNo:
%d\n",errnum);
          //perror("Meaning :");
          exit(1);
        }

        for( ; ;) {
           if(( nsockfd = accept(sockfd ,(struct sockaddr *) &cliaddr
, &clilen) ) < 0 )
           {
                  errnum = errno;
                  printf("Error accepting connection. ErrorNo:
%d\n",errnum);
                  //perror("Meaning :");
                  close(nsockfd);
                  exit(1);
           }
           else
           {
                //nsockfd = accept(sockfd,(struct sockaddr *)
&cliaddr, &clilen);
                        m = read(nsockfd, msg, 1000);
                        n = write(nsockfd, msg, 1000);

printf("-------------------------------------\n");
                        msg[m] = '\0';
                        printf("Received the following message\n");
                        printf("%s", msg);
                        close(nsockfd);
            }
        }

        close(sockfd);
        return 0;

Quote:}

 
 
 

Error in accept() system call

Post by nzwwb.. » Fri, 15 Aug 2003 12:48:41


Try this:

|        }
|
|        for( ; ;) {
                clilen = sizeof(cliaddr);
|           if(( nsockfd = accept(sockfd ,(struct sockaddr *) &cliaddr
|, &clilen) ) < 0 )
|           {

See this paragraph in man 2 accept for the reason.

The  argument addr is a pointer to a sockaddr structure. This structure
is filled in with the address of the connecting entity, as known to the
communications  layer.   The  exact format of the address passed in the
addr parameter is determined by the socket's family (see socket(2)  and
the  respective  protocol man pages).  The addrlen argument is a value-
                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
result parameter: it should initially contain the size of the structure
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pointed  to  by  addr;  on return it will contain the actual length (in
^^^^^^^^^^^^^^^^^^^^^
bytes) of the address returned. When addr is NULL nothing is filled in.

By the way if you compile with -Wall you will notice lots of warnings
which you should fix if you really want your code to be portable. Also
note that inet_addr is deprecated and it returns the wrong type for
assignment to sin_addr anyway.
--

 
 
 

Error in accept() system call

Post by Santosh Golec » Sat, 16 Aug 2003 00:52:19


Thanks...it worked. The only change I made as per your recommendation
was to add the following statement before the accept system call.

clilen = sizeof(cliaddr);

Thanks


> Try this:

> |        }
> |
> |        for( ; ;) {
>  clilen = sizeof(cliaddr);
> |           if(( nsockfd = accept(sockfd ,(struct sockaddr *) &cliaddr
> |, &clilen) ) < 0 )
> |           {

> See this paragraph in man 2 accept for the reason.

> The  argument addr is a pointer to a sockaddr structure. This structure
> is filled in with the address of the connecting entity, as known to the
> communications  layer.   The  exact format of the address passed in the
> addr parameter is determined by the socket's family (see socket(2)  and
> the  respective  protocol man pages).  The addrlen argument is a value-
>                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> result parameter: it should initially contain the size of the structure
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> pointed  to  by  addr;  on return it will contain the actual length (in
> ^^^^^^^^^^^^^^^^^^^^^
> bytes) of the address returned. When addr is NULL nothing is filled in.

> By the way if you compile with -Wall you will notice lots of warnings
> which you should fix if you really want your code to be portable. Also
> note that inet_addr is deprecated and it returns the wrong type for
> assignment to sin_addr anyway.
> --

 
 
 

Error in accept() system call

Post by beltor » Sat, 16 Aug 2003 07:44:42



> On 13 Aug 2003 00:02:47 -0700,

> >extern int errno;

> Carefull,  these days errno is often a macro which calls a function returning
> a pointer to an int and the macro then dereference this macro so it appears to
> work like a variable called errno.

> >int errnum;
> >main() { etc etc

> Example from GNU glibc2:

> /usr/include/bits/errno.h:#define errno (*__errno_location ())

> This is necessary for supporting threaded code.

> The proper way to define errno is to #include <errno.h>

> Villy

I didn't suggest taking out '#include <errno.h>'; but thanks for
setting that straight; for some reason I thought you had to declare
errno before you used it directly....  dunno why.

-t.