Error in send and recv(). Please help. - Unix

This is a discussion on Error in send and recv(). Please help. - Unix ; I wrote a client and server program in C. The server is actually IPv6 socket and client is IPv4. They both use the storage structure sockaddr_storage to cast to IPv6 and IPv4. The client and server are connected but the ...

+ Reply to Thread
Results 1 to 6 of 6

Thread: Error in send and recv(). Please help.

  1. Error in send and recv(). Please help.

    I wrote a client and server program in C. The server is actually IPv6
    socket and client is IPv4. They both use the storage structure
    sockaddr_storage to cast to IPv6 and IPv4.

    The client and server are connected but the server cannot send the
    data to the client. I am pasting the code. Do you see any obvious
    mistake in the code.

    Please help. Every help is greatly appreciated.

    Thanks.


    I compiled the code using gcc -client.c -o client and gcc server.c -o
    server, and then running the ./server and ./client 127.0.0.1.

    ***********Server Code*******************
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include

    #define PORT 3500
    #define LISTEN_COUNT 5
    #define INET_ADDRSTRLEN 16
    #define INET6_ADDRSTRLEN 46


    int main()
    {
    int sockfd, new_fd;

    char str[INET6_ADDRSTRLEN];

    /* Storage struct */
    struct sockaddr_storage my_addr, their_addr;

    /* IPv6 struct */
    struct sockaddr_in6 *in6;
    struct sockaddr_in6 *in6their;

    socklen_t my_addrlen = sizeof(my_addr);
    socklen_t their_addrlen = sizeof(their_addr);

    printf("\n Length of my_addr = %d\n", my_addrlen);

    sockfd = socket(AF_INET6, SOCK_STREAM, 0);
    if (sockfd == -1){
    printf("\n Error creating socket");
    exit(1);
    }

    /* Casting Storage to IPv6 */
    in6 = (struct sockaddr_in6 *) &my_addr;

    /* Populating Values */
    // (*in6).sin6_len = sizeof(struct sockaddr_in6);
    (*in6).sin6_family = AF_INET6;
    (*in6).sin6_port = htons(PORT);
    (*in6).sin6_addr = in6addr_any; //loopback;

    /* binding */
    if ( (bind(sockfd, (struct sockaddr *) &my_addr, my_addrlen) == -1) )
    {
    printf("\n Can't bind");
    exit(1);
    }

    /* Listening */
    if (listen(sockfd, LISTEN_COUNT) == -1) {
    printf("\n Error( listening");
    exit(1);
    }

    printf("\n Server: I am listening\n");

    /* Accept, Print and Send back through another child process */
    while (1){
    if ( (new_fd = accept(sockfd, (struct sockaddr *) &their_addr,
    &their_addrlen) == -1) ){
    printf("\n Can't accept");
    continue;
    }
    /* Casting Storage to IPv4 */
    in6their = (struct sockadd_in6 *) &their_addr;


    printf("\n Server got connection from %s\n", inet_ntop(AF_INET6,
    &( (*in6their).sin6_addr), str, sizeof(str) ) );

    if (!fork()) { // this is the child process
    close(sockfd); // child doesn't need the listener
    if (send(new_fd, "Hello World", sizeof("Hello World"), 0) == -1) {
    printf("Error sending");
    close(new_fd);
    exit(0);
    }
    }

    close(new_fd); // parent doesn't need this
    }

    return 0;
    }


    ***********Client Code*******************

    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include

    #define PORT 3500
    #define MAXDATASIZE 100

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

    int sockfd, numbytes;
    char buf[MAXDATASIZE];

    struct sockaddr_storage my_addr;
    struct hostent *he;

    struct sockaddr_in *in4;

    if (argc != 2){
    printf("\n Incorrect usage\n");
    }


    if ( (he=gethostbyname2(argv[1], AF_INET) ) == NULL ) {
    printf("\n Error in gethostbyname\n");
    exit(1);
    }

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1){
    printf("\n Error creating socket\n");
    exit(1);
    }

    in4 = (struct sockaddr_in *) &my_addr;

    (*in4).sin_family = AF_INET;
    (*in4).sin_port = htons(PORT);
    (*in4).sin_addr = *((struct in_addr *) he->h_addr);

    memset((*in4).sin_zero, '\0', sizeof((*in4).sin_zero) );

    if ( connect(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) ==
    -1) {
    printf("\n Error Connecting\n");
    exit(1);
    }

    printf("\n Client: I have been connected\n");

    if ((numbytes=recv(sockfd, buf, MAXDATASIZE-1,0)) == -1) {
    printf("\n Error recieving\n");
    exit(1);
    }

    printf("\n Client: I have received data\n");


    buf[numbytes] = '\0';
    printf("\n Received: %s\n", buf);

    close(sockfd);

    return 0;

    }


  2. Re: Error in send and recv(). Please help.

    In article
    <726df89a-0bd9-48db-8a53-33ad220f00e4@c22g2000prc.googlegroups.com>,
    DanielJohnson wrote:

    > I wrote a client and server program in C. The server is actually IPv6
    > socket and client is IPv4. They both use the storage structure
    > sockaddr_storage to cast to IPv6 and IPv4.
    >
    > The client and server are connected but the server cannot send the
    > data to the client. I am pasting the code. Do you see any obvious
    > mistake in the code.


    What error is it getting? You should use perror() rather than just
    printing "Error sending".

    >
    > Please help. Every help is greatly appreciated.
    >
    > Thanks.
    >
    >
    > I compiled the code using gcc -client.c -o client and gcc server.c -o
    > server, and then running the ./server and ./client 127.0.0.1.
    >
    > ***********Server Code*******************
    > #include
    > #include
    > #include
    > #include
    > #include
    > #include
    > #include
    > #include
    >
    > #define PORT 3500
    > #define LISTEN_COUNT 5
    > #define INET_ADDRSTRLEN 16
    > #define INET6_ADDRSTRLEN 46
    >
    >
    > int main()
    > {
    > int sockfd, new_fd;
    >
    > char str[INET6_ADDRSTRLEN];
    >
    > /* Storage struct */
    > struct sockaddr_storage my_addr, their_addr;
    >
    > /* IPv6 struct */
    > struct sockaddr_in6 *in6;
    > struct sockaddr_in6 *in6their;
    >
    > socklen_t my_addrlen = sizeof(my_addr);
    > socklen_t their_addrlen = sizeof(their_addr);
    >
    > printf("\n Length of my_addr = %d\n", my_addrlen);
    >
    > sockfd = socket(AF_INET6, SOCK_STREAM, 0);
    > if (sockfd == -1){
    > printf("\n Error creating socket");
    > exit(1);
    > }
    >
    > /* Casting Storage to IPv6 */
    > in6 = (struct sockaddr_in6 *) &my_addr;
    >
    > /* Populating Values */
    > // (*in6).sin6_len = sizeof(struct sockaddr_in6);
    > (*in6).sin6_family = AF_INET6;
    > (*in6).sin6_port = htons(PORT);
    > (*in6).sin6_addr = in6addr_any; //loopback;
    >
    > /* binding */
    > if ( (bind(sockfd, (struct sockaddr *) &my_addr, my_addrlen) == -1) )
    > {
    > printf("\n Can't bind");
    > exit(1);
    > }
    >
    > /* Listening */
    > if (listen(sockfd, LISTEN_COUNT) == -1) {
    > printf("\n Error( listening");
    > exit(1);
    > }
    >
    > printf("\n Server: I am listening\n");
    >
    > /* Accept, Print and Send back through another child process */
    > while (1){
    > if ( (new_fd = accept(sockfd, (struct sockaddr *) &their_addr,
    > &their_addrlen) == -1) ){
    > printf("\n Can't accept");
    > continue;
    > }
    > /* Casting Storage to IPv4 */
    > in6their = (struct sockadd_in6 *) &their_addr;
    >
    >
    > printf("\n Server got connection from %s\n", inet_ntop(AF_INET6,
    > &( (*in6their).sin6_addr), str, sizeof(str) ) );
    >
    > if (!fork()) { // this is the child process
    > close(sockfd); // child doesn't need the listener
    > if (send(new_fd, "Hello World", sizeof("Hello World"), 0) == -1) {
    > printf("Error sending");
    > close(new_fd);
    > exit(0);
    > }
    > }
    >
    > close(new_fd); // parent doesn't need this
    > }
    >
    > return 0;
    > }
    >
    >
    > ***********Client Code*******************
    >
    > #include
    > #include
    > #include
    > #include
    > #include
    > #include
    > #include
    > #include
    >
    > #define PORT 3500
    > #define MAXDATASIZE 100
    >
    > int main(int argc, char *argv[])
    > {
    >
    > int sockfd, numbytes;
    > char buf[MAXDATASIZE];
    >
    > struct sockaddr_storage my_addr;
    > struct hostent *he;
    >
    > struct sockaddr_in *in4;
    >
    > if (argc != 2){
    > printf("\n Incorrect usage\n");
    > }
    >
    >
    > if ( (he=gethostbyname2(argv[1], AF_INET) ) == NULL ) {
    > printf("\n Error in gethostbyname\n");
    > exit(1);
    > }
    >
    > sockfd = socket(AF_INET, SOCK_STREAM, 0);
    > if (sockfd == -1){
    > printf("\n Error creating socket\n");
    > exit(1);
    > }
    >
    > in4 = (struct sockaddr_in *) &my_addr;
    >
    > (*in4).sin_family = AF_INET;
    > (*in4).sin_port = htons(PORT);
    > (*in4).sin_addr = *((struct in_addr *) he->h_addr);
    >
    > memset((*in4).sin_zero, '\0', sizeof((*in4).sin_zero) );
    >
    > if ( connect(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) ==
    > -1) {
    > printf("\n Error Connecting\n");
    > exit(1);
    > }
    >
    > printf("\n Client: I have been connected\n");
    >
    > if ((numbytes=recv(sockfd, buf, MAXDATASIZE-1,0)) == -1) {
    > printf("\n Error recieving\n");
    > exit(1);
    > }
    >
    > printf("\n Client: I have received data\n");
    >
    >
    > buf[numbytes] = '\0';
    > printf("\n Received: %s\n", buf);
    >
    > close(sockfd);
    >
    > return 0;
    >
    > }


    --
    Barry Margolin, barmar@alum.mit.edu
    Arlington, MA
    *** PLEASE post questions in newsgroups, not directly to me ***
    *** PLEASE don't copy me on replies, I'll read them in the group ***

  3. Re: Error in send and recv(). Please help.

    On Wed, 24 Sep 2008 13:13:14 -0700 (PDT),
    DanielJohnson wrote:


    > /* Accept, Print and Send back through another child process */
    > while (1){
    > if ( (new_fd = accept(sockfd, (struct sockaddr *) &their_addr,
    > &their_addrlen) == -1) ){


    [...]

    > if (!fork()) { // this is the child process
    > close(sockfd); // child doesn't need the listener
    > if (send(new_fd, "Hello World", sizeof("Hello World"), 0) == -1) {


    new_fd is not a socket. It's a file descriptor. Use write(new_fd,...)
    instead of send.

    Martien
    --
    |
    Martien Verbruggen | "In a world without fences,
    | who needs Gates?"
    |

  4. Re: Error in send and recv(). Please help.

    DanielJohnson wrote:
    >I wrote a client and server program in C. The server is actually IPv6
    >socket and client is IPv4. They both use the storage structure
    >sockaddr_storage to cast to IPv6 and IPv4.


    Before I begin, I'm going to take this opportunity to say that I've
    recently updated Beej's Guide to Network Programming (a decade-old
    document) to include IPv6 stuff.

    It's got a lot of new and changed material, and I'm sure I have more
    than my fair share of mistakes in it, but I'd surely appreciate
    suggestions from the lot of you Unixy-types...

    http://beej.us/guide/bgnet/


    >Do you see any obvious mistake in the code.


    The dealbreaker isn't obvious, but it's a classic C mistake. There are
    a few other things, too.

    >I compiled the code using gcc -client.c -o client and gcc server.c -o
    >server, and then running the ./server and ./client 127.0.0.1.


    Use -Wall when compiling; it'll catch more errors, like this:

    $ cc -Wall -o server server.c
    server.c: In function 'main':
    server.c:73: warning: assignment from incompatible pointer type

    Ok, let's go!

    >***********Server Code*******************
    > sockfd = socket(AF_INET6, SOCK_STREAM, 0);
    > if (sockfd == -1){
    > printf("\n Error creating socket");


    use perror("socket") here--it'll tell you the error. In fact, perror()
    will work for you everywhere except for gethostbyname() and
    getaddrinfo(), pretty much.

    > (*in6).sin6_family = AF_INET6;


    More readable C shorthand for the above line is:

    in6->sin6_family = AF_INET6;

    > (*in6).sin6_addr = in6addr_any; //loopback;


    This isn't actually the loopback address, necessarily. It's any address
    on this host. (Compare to in6addr_loopback.)

    > if ( (new_fd = accept(sockfd, (struct sockaddr *) &their_addr,
    >&their_addrlen) == -1) ){


    There it is, the classic C error. What's wrong? Parenthesis mismatch.
    The comparison between accept() and -1 is taking place first, resulting
    in false (0), which is then assigned into new_fd every time. You want
    this:

    if ( (new_fd = accept(sockfd, (struct sockaddr *) &their_addr,
    &their_addrlen) ) == -1 ){
    ^ ^

    Using perror() on that line told me "send: Socket operation on
    non-socket". Which got me thinking about why new_fd wasn't a socket
    when it was clearly returned by accept(). It was getting set to 0, as
    we saw above, and file descriptor 0 is stdin, which is not a socket. So
    it all makes sense.

    > in6their = (struct sockadd_in6 *) &their_addr;


    There's the warning. struct sockadd_in6 (missing an "r") is not the
    type of in6their. It's a cast to a pointer of an incomplete type, but
    not one that has been declared--I'm a little surprised the compiler
    didn't complain more about this.

    > if (!fork()) { // this is the child process
    > close(sockfd); // child doesn't need the listener
    > if (send(new_fd, "Hello World", sizeof("Hello World"), 0) == -1) {
    > printf("Error sending");
    > close(new_fd);
    > exit(0);
    > }

    exit(0); // exit here! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    > }


    You need to exit the child process, or else it'll loop back around and
    try to accept() along with the parent. You don't want that.

    >****************Client Code*******************
    > if (argc != 2){
    > printf("\n Incorrect usage\n");

    exit(1); // <<<<<<<<<<<<<<<<<<
    > }


    You probably don't want to keep running in that case.

    > memset((*in4).sin_zero, '\0', sizeof((*in4).sin_zero) );


    You should #include for memset(). Also, I've heard that
    setting sin_zero to zero isn't strictly necessary, but I haven't seen
    the definitive answer.

    I think that's all I changed...hopefully that'll get it going.

    HTH!
    -Beej


  5. Re: Error in send and recv(). Please help.

    In article ,
    Martien Verbruggen wrote:

    > On Wed, 24 Sep 2008 13:13:14 -0700 (PDT),
    > DanielJohnson wrote:
    >
    >
    > > /* Accept, Print and Send back through another child process */
    > > while (1){
    > > if ( (new_fd = accept(sockfd, (struct sockaddr *) &their_addr,
    > > &their_addrlen) == -1) ){

    >
    > [...]
    >
    > > if (!fork()) { // this is the child process
    > > close(sockfd); // child doesn't need the listener
    > > if (send(new_fd, "Hello World", sizeof("Hello World"), 0) == -1) {

    >
    > new_fd is not a socket. It's a file descriptor. Use write(new_fd,...)
    > instead of send.


    Wrong, it's a file descriptor that refers to a socket. Accept() always
    returns a socket file descriptor.

    --
    Barry Margolin, barmar@alum.mit.edu
    Arlington, MA
    *** PLEASE post questions in newsgroups, not directly to me ***
    *** PLEASE don't copy me on replies, I'll read them in the group ***

  6. Re: Error in send and recv(). Please help.

    Thanks for all the replies. It helped me figure out and I was able to
    run the program.

+ Reply to Thread