UNIX Socket FAQ

A forum for questions and answers about network programming on Linux and all other Unix-like systems

You are not logged in.

#1 2013-04-02 12:50 AM

tera
Guest

Threaded Server is not responding

// Server code
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <strings.h>
#include <stdlib.h>
#include <thread.h>
#include <netdb.h>
#include <netinet/in.h>

#ifndef SUN_LEN
#define SUN_LEN(su) \
   (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
#endif

int sockfd;
struct sockaddr_un sock_address;
struct sockaddr_un cli_sock_address;
socklen_t address_length;  // length of server address

void onintr(int param)
{
        close(sockfd);
        unlink(sock_address.sun_path);
        exit(1);
}

void* search_author(void* para);

int main()
{
        int  bytes, rv;
        char buf[256];
        thread_t chld_thr;
        struct addrinfo hints, *servinfo, *p;
        memset(&hints, 0, sizeof (hints));
        hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6
        hints.ai_socktype = SOCK_DGRAM;         // SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE; // use my IP address

        if ((rv = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0)
        {
           fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
           exit(1);
        }

        // loop through all the results and bind to the first we can
        for(p = servinfo; p != NULL; p = p->ai_next)
        {
           if ((sockfd = socket(p->ai_family, p->ai_socktype,
            p->ai_protocol)) == -1)
           {
              perror("socket");
              continue;
           }

           if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1)
           {
              close(sockfd);
              perror("bind");
              continue;
           }

           break; // if we get here, it is connected successfully
        }

        if (p == NULL)
        {
           // looped off the end of the list with no successful bind
           fprintf(stderr, "failed to bind socket\n");
           exit(2);
        }

        freeaddrinfo(servinfo); // all done with this structure
        signal(SIGINT, onintr);

        for(;;)
        { // create a new thread to process incoming request
            thr_create(NULL, 0, search_author, (void *) sockfd, THR_DETACHED, &chld_thr);
        }

}

void* search_author(void* para)
{
   int mysocfd = (int) para;
   char buf[256];
   int  bytes;
   struct sockaddr_storage peer_addr;
   socklen_t peer_addr_len;

   bzero(buf, sizeof(buf));

   bytes = recvfrom(mysocfd, buf, sizeof(buf), 0, (struct sockaddr *) &peer_addr, &peer_addr_len);
   buf[bytes] = '\0';
   printf("Server received: %s\n", buf);

   if (!strcmp(buf, "Hobbit"))
        write(mysocfd, "Tolkien", 7);
   else
        write(mysocfd, "Author Unknown", 14);

   close(mysocfd);    // done with this client
   thr_exit((void *) 0);      // child process terminates
}

#2 2013-04-02 12:37 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,839
Website

Re: Threaded Server is not responding

Your server is creating an infinite number of threads non-stop!  That's surely not desired behavior...  You just spin in a for(;;) loop, creating thread after thread...  Unless that thr_create() function of yours blocks until the thread terminates?  (Which would seem to be a pretty useless interface for a threads API...)

Your client is doing a sendto() to a completely unspecified address, because you never fill in "peer_addr" at all...  Also, if these are SOCK_DGRAM sockets (presumably UDP), why bother doing connect() at all?  Or, if you're going to connect(), then why not just use send() instead of sendto()?

And, weirdly your server uses recvfrom() to read the client's message, but yet uses a simple write() to reply!  I don't think that will work properly, since you don't connect() the UDP socket on the server side...  You want to be using sendto() there...  Also, you have a potential buffer overflow where you add the null termination, since the return value of recvfrom() may be the full sizeof(buf)...  (Plus, the client is sending you the full buffer, including null char, so it would seem unnecessary anyway...  But, you probably do want to be using the same buffer sizes in both places; right now, the client is sending 500 bytes, and the server is only reading 256!)

Offline

#3 2013-04-23 09:36 AM

Tera
Guest

Re: Threaded Server is not responding

Thanks Rob for the reply, I am going to simplify my codes to get the server/client communicating via
AF_INET first; then add thread later. The following server code didn't receive any data from the client,
I wonder what I am missing or do wrong here.

// Server code

// Server code
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <strings.h>
#include <stdlib.h>
#include <thread.h>
#include <netdb.h>
#include <netinet/in.h>

#ifndef SUN_LEN
#define SUN_LEN(su) \
   (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
#endif

int sockfd;
struct sockaddr_un sock_address;
struct sockaddr_un cli_sock_address;
socklen_t address_length;  // length of server address

int main()
{
        int  bytes;
        char buf[500];
        thread_t chld_thr;
        int rv;
        struct addrinfo hints, *servinfo, *p;
        struct  sockaddr_in peer_addr;
        socklen_t peer_addr_len;

        memset(&hints, 0, sizeof (hints));
        hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6
        hints.ai_socktype = SOCK_DGRAM;         // SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE; // use my IP address

        if ((rv = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0)
        {
           fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
           exit(1);
        }

        // loop through all the results and bind to the first socket file
        // descriptor found
        for(p = servinfo; p != NULL; p = p->ai_next)
        {
           if ((sockfd = socket(p->ai_family, p->ai_socktype,
            p->ai_protocol)) == -1)
           {
              perror("socket");
              continue;
           }

           if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1)
           {
              close(sockfd);
              perror("bind");
              continue;
           }

           break; // if we get here, connected successfully
        }

        if (p == NULL)
        {
           // looped off the end of the list with no successful bind
           fprintf(stderr, "failed to bind socket\n");
           exit(2);
        }

        freeaddrinfo(servinfo); // all done with this structure

        for(;;)
        {
           bytes = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *) &peer_addr, &peer_addr_len);
           printf("Server received %s\n", buf);
        }
}

// Client code

// client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <stdlib.h>
#include <netdb.h>
#define PORT                    3490

main()
{
        int     bytes;
        struct  sockaddr_in peer_addr;
        char    authorname[500];
        char    bookname[500];
        int sockfd;
        struct addrinfo hints, *servinfo, *p;
        int rv;
        int peer_addr_len;

        memset(&hints, 0, sizeof (struct addrinfo));
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_flags = AI_PASSIVE; // use my IP address // 0;
        hints.ai_protocol = 0;          // any protocol

        if ((rv = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0)
        {
           fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
           exit(1);
        }

        // loop through all the results and connect to the first we can
        for(p = servinfo; p != NULL; p = p->ai_next)
        {
           if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
           {
                perror("socket");
                continue;
           }

           break; // if we get here, connected successfully
        }

        if (p == NULL)
        {
           // looped off the end of the list with no connection
           fprintf(stderr, "failed to connect\n");
           exit(2);
        }

        bzero((char* ) &peer_addr, sizeof (peer_addr));
        bcopy(p->ai_addr, (char*) &peer_addr.sin_addr, p->ai_addrlen);
        peer_addr.sin_port = PORT;
        peer_addr.sin_family = p->ai_family;

        // free serverinfo pointer
        freeaddrinfo(servinfo); // all done with this structure

        // sendto(sockfd, bookname, sizeof(bookname), 0, (struct sockaddr *) &peer_addr, sizeof (peer_addr));
        sendto(sockfd, "hello", 5, 0, (struct sockaddr *) &peer_addr, sizeof (peer_addr));
}

#4 2013-04-23 12:16 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,839
Website

Re: Threaded Server is not responding

You say you're using AF_INET, but since you specify AF_UNSPEC for getaddrinfo() hints, you can't be sure of that...  You may be using AF_UNIX or AF_INET6 or anything else really...  As such, it's wrong to use "sockaddr_in" or "sockaddr_un" structs specifically, since you don't know which you'll actually need...  In that case, you should be using "sockaddr_storage", which is guaranteed large enough for any of the sockaddrs...

But, the most important thing is: in the server, just prior to every recvfrom(), you should be setting "peer_addr_len = sizeof (peer_addr);"...  It uses the value in there initially as the max address size it can store, and will update that value with the true address size after...

Also, the client doesn't want AI_PASSIVE in its getaddrinfo() flags; that's for servers only...

Also, your copying of the address in the client code is wrong...  "p->ai_addr" contains the full sockaddr, not merely the IP...  So, these lines:

bzero((char* ) &peer_addr, sizeof (peer_addr));
        bcopy(p->ai_addr, (char*) &peer_addr.sin_addr, p->ai_addrlen);
        peer_addr.sin_port = PORT;
        peer_addr.sin_family = p->ai_family;

Should be replaced by just this:

memcpy (&peer_addr, p->ai_addr, p->ai_addrlen);

(Or, you can use the horrid old bcopy() instead, if you prefer, but I like memcpy()'s saner argument order...)

But, again, your "peer_addr" should be a "struct sockaddr_storage", rather than "sockaddr_in", as well, since you're not really sure what address family you're actually using here...  Alternatively, you could replace the AF_UNSPEC in the hints with AF_INET to be sure you're using IPv4, and so "sockaddr_in" would be sufficient...

Offline

#5 2013-04-24 05:16 AM

Tera
Guest

Re: Threaded Server is not responding

Thanks Rob. Both talked to each other via Internet domain datagram socket now.
Now is additional complexity:
I like the Server to send an Acknowledgement message back to the Client.
Likewise, the Client should receive back this Acknowledgement message from Server
and prints it out. In essence, each node has dual roles: Server and Client.

(I have to use thread in this project. Right now, I am simply spawning a thread whenever
Server receives input from clients. Once the errors are ironed out, I'd like to spawn a thread
each time a unique client (using client ID, maybe?) sends it something.
I wonder if it's possible to use thread entirely without forking in my case? )

My current client code seems to block by recvfrom(), waiting forever for inputs from the server;
but my server codes do send out message.
Not sure what my errors are located, so I am going to post the entire codes below.

Thanks in advance for the help.
Regards,

// Server

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <strings.h>
#include <stdlib.h>
#include <thread.h>
#include <netdb.h>
#include <netinet/in.h>

#ifndef SUN_LEN
#define SUN_LEN(su) \
   (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
#endif

int sockfd;
struct sockaddr_un sock_address;
struct sockaddr_un cli_sock_address;
socklen_t address_length;  // length of server address

void* acknowlegement(void* arg);

int main()
{
        int  bytes;
        char buf[500];
        thread_t chld_thr;
        int rv;
        struct addrinfo hints, *servinfo, *p;
        struct  sockaddr_in peer_addr;
        socklen_t peer_addr_len;

        memset(&hints, 0, sizeof (hints));
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_DGRAM;         // SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE; // use my IP address

        if ((rv = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0)
        {
           fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
           exit(1);
        }

        // loop through all the results and bind to the first socket FD found
        for(p = servinfo; p != NULL; p = p->ai_next)
        {
           if ((sockfd = socket(p->ai_family, p->ai_socktype,
            p->ai_protocol)) == -1)
           {
              perror("socket");
              continue;
           }

           if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1)
           {
              close(sockfd);
              perror("bind");
              continue;
           }

           break; // if we get here, connected successfully
        }

        if (p == NULL)
        {
           // looped off the end of the list with no successful bind
           fprintf(stderr, "failed to bind socket\n");
           exit(2);
        }

        freeaddrinfo(servinfo); // all done with this structure

        for(;;)
        {
           memset(buf, 0, sizeof (buf));
           peer_addr_len = sizeof (peer_addr);
           bytes = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *) &peer_addr, &peer_addr_l
en);
           printf("Server received %s\n", buf);

           // create a new thread to process incoming request
           thr_create(NULL, 0, acknowlegement, (void *) 0, THR_DETACHED, &chld_thr);
        }

}

// Send a message back to client to acknowledge that server receives the message
void* acknowlegement(void* arg)
{

   int sd_to_send_back;
   int rv;
   struct addrinfo hints;
   struct addrinfo *peerinfo;
   struct addrinfo *p;
   struct sockaddr_in peer_addr;

   // 1. Create a new socket to send info back to client from server
   sd_to_send_back = socket (AF_INET, SOCK_DGRAM, 0);

   // 2. Set up the peer addr
   hints.ai_family = AF_INET;
   hints.ai_socktype = SOCK_DGRAM;
   hints.ai_protocol = 0;          // any protocol

   if ((rv = getaddrinfo(NULL, "7001", &hints, &peerinfo)) != 0)
   {
      fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
      exit(1);
   }

   // loop through all the results and connect to the first we can
   for(p = peerinfo; p != NULL; p = p->ai_next)
   {
      if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
      {
          perror("socket");
          continue;
      }

      break; // if we get here, connected successfully
   }

   if (p == NULL)
   {
      // looped off the end of the list with no connection
      fprintf(stderr, "failed to connect\n");
      exit(2);
   }

   memcpy(&peer_addr, p->ai_addr, p->ai_addrlen);

   // free serverinfo pointer
   freeaddrinfo(peerinfo); // all done with this structure

   // 3. Send message out of the new socket
   sendto(sockfd, "Got your message", 16, 0, (struct sockaddr *) &peer_addr, sizeof (peer_addr));

   // 4. Close the new socket
   close(sd_to_send_back);

// Client

// client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <stdlib.h>
#include <netdb.h>

#define PORT                    3490

main()
{
        // variables and structs for client
        int     bytes;
        int     sockfd;
        int     rv;
        int     peer_addr_len;
        struct  sockaddr_in peer_addr;
        char    authorname[500];
        char    bookname[500];
        char    buf[500];
        struct addrinfo hints, *servinfo, *p;

        // variables and structs for server
        int                     s_sockfd;
        int                     s_bytes;
        char                    s_buf[500];
        // thread_t             s_chld_thr;
        int                     s_rv;
        struct addrinfo         s_hints;
        struct addrinfo         *s_servinfo;
        struct addrinfo         *s_p;
        struct sockaddr_in      s_peer_addr;
        socklen_t               s_peer_addr_len;

////////////////////////////////////////////////////////////
// This section deals with sending data to Server
////////////////////////////////////////////////////////////
        memset(&hints, 0, sizeof (struct addrinfo));
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_protocol = 0;          // any protocol

        if ((rv = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0)
        {
           fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
           exit(1);
        }

        // loop through all the results and connect to the first we can
        for(p = servinfo; p != NULL; p = p->ai_next)
        {
           if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
           {
                perror("socket");
                continue;
           }

           break; // if we get here, connected successfully
        }

        if (p == NULL)
        {
           // looped off the end of the list with no connection
           fprintf(stderr, "failed to connect\n");
           exit(2);
        }

        memcpy(&peer_addr, p->ai_addr, p->ai_addrlen);
        freeaddrinfo(servinfo); // all done with this structure

        sendto(sockfd, "hello", 5, 0, (struct sockaddr *) &peer_addr, sizeof (peer_addr));


//////////////////////////////////////////////////////////////////
// This section deals with receiving back data from Server.
//////////////////////////////////////////////////////////////////
       memset(&s_hints, 0, sizeof (s_hints));
        s_hints.ai_family = AF_INET;
        s_hints.ai_socktype = SOCK_DGRAM;         // SOCK_STREAM;
        s_hints.ai_flags = AI_PASSIVE; // use my IP address

        if ((rv = getaddrinfo(NULL, "7001", &s_hints, &s_servinfo)) != 0)
        {
           fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s_rv));
           exit(1);
        }

        // loop through all the results and bind to the first socket FD found
        for(s_p = s_servinfo; s_p != NULL; s_p = s_p->ai_next)
        {
           if ((s_sockfd = socket(s_p->ai_family, s_p->ai_socktype,
            s_p->ai_protocol)) == -1)
           {
              perror("socket");
              continue;
           }

           if (bind(s_sockfd, s_p->ai_addr, s_p->ai_addrlen) == -1)
           {
              close(s_sockfd);
              perror("bind");
              continue;
           }

           break; // if we get here, connected successfully
        }

        if (s_p == NULL)
        {
           // looped off the end of the list with no successful bind
           fprintf(stderr, "failed to bind socket\n");
           exit(2);
        }

        freeaddrinfo(s_servinfo); // all done with this structure

           memset(s_buf, 0, sizeof (s_buf));

           // read message back from the server
           s_peer_addr_len = sizeof (s_peer_addr);
           s_bytes = recvfrom(s_sockfd, s_buf, sizeof(s_buf), 0, (struct sockaddr *) &s_peer_addr, &s
_peer_addr_len);
           printf("Client received %s\n", s_buf);
}

#6 2013-04-24 12:48 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,839
Website

Re: Threaded Server is not responding

You really don't need to create 2 separate sockets in each app in order to both send and receive in each...  You can use the same socket for both...  The server has the client's address in "peer_addr" after the recvfrom() completes, so all it needs to do at that point is sendto() and pass that very same "peer_addr" to it...  And, the client can just recvfrom() on the same socket it just did the sendto() on...  (Though, traditionally yes you'd want to bind() to a specific port# in the client as well as the server, but it's not really necessary, since the first sendto() you do through the socket will auto-bind you to a random ephemeral port#...)

But, your overly complicated double socket approach should be workable as well...  The thing is, you'll want to setup both sockets in the client BEFORE you have it do the sendto() to the server...  Otherwise, you're relying on timing to get things right...  Ie: the server may receive the client's message and send back a reply before the client has even setup its socket and tried to receive on it!

Also, in the server thread code, you never memset() the "hints" full of nulls, so you're leaving some random trash in there, which may be messing things up...  Also, what's up with the separate "sd_to_send_back"?  You seem to actually use "sockfd", which you probably DON'T want to be using, since that's a global, and you'll be overwriting your main()'s use of "sockfd", since threads all share the same memory, so changing a global variable in one thread will affect all others...

Offline

#7 2013-04-24 10:24 PM

Tera
Guest

Re: Threaded Server is not responding

Hi, Rob:
I reduced my codes to use the same peer information as you suggested,
but I got a question.

In server code, if I re-use the same peer_addr information, what socket file descriptor
should I use for sendto() function? You mentioned that I should not be using the global sockfd,
does it mean that I need to create a new socket as follows?

sd_to_send_back = socket (AF_INET, SOCK_DGRAM, 0);

Thanks.

Here's my currently updated (but broken) codes:

// Server

// Server code
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <strings.h>
#include <stdlib.h>
#include <thread.h>
#include <netdb.h>
#include <netinet/in.h>

#ifndef SUN_LEN
#define SUN_LEN(su) \
   (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
#endif

int sockfd;
struct  sockaddr_in peer_addr;
socklen_t peer_addr_len;

void* acknowledgement(void* arg);

int main()
{
        int  bytes;
        char buf[500];
        thread_t chld_thr;
        int rv;
        struct addrinfo hints, *servinfo, *p;
        size_t  threadStatus;

        memset(&hints, 0, sizeof (hints));
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_DGRAM;         // SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE; // use my IP address

        if ((rv = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0)
        {
           fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
           exit(1);
        }

        // loop through all the results and bind to the first socket FD found
        for(p = servinfo; p != NULL; p = p->ai_next)
        {
           if ((sockfd = socket(p->ai_family, p->ai_socktype,
            p->ai_protocol)) == -1)
           {
              perror("socket");
              continue;
           }

           if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1)
           {
              close(sockfd);
              perror("bind");
              continue;
           }

           break; // if we get here, connected successfully
        }

        if (p == NULL)
        {
           // looped off the end of the list with no successful bind
           fprintf(stderr, "failed to bind socket\n");
           exit(2);
        }

        freeaddrinfo(servinfo); // all done with this structure

        for(;;)
        {
           memset(buf, 0, sizeof (buf));
           peer_addr_len = sizeof (peer_addr);
           bytes = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *) &peer_addr, &peer_addr_len);
           printf("Server received %s\n", buf);

           // create a new thread to process incoming request
           thr_create(NULL, 0, acknowledgement, (void *) 0, THR_DETACHED, &chld_thr);

//         thr_join(chld_thr, 0 , (void*) &threadStatus);
        }

}

// Send a message back to client to acknowledge that server receives the message
void* acknowledgement(void* arg)
{
   // 3. Send message out of the new socket
   sendto(sockfd, "Got your message", 16, 0, (struct sockaddr *) &peer_addr, sizeof (peer_addr));
}

// Client code

// client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <stdlib.h>
#include <netdb.h>

#define PORT                    3490

main()
{
        // variables and structs for client
        int     bytes;
        int     sockfd;
        int     rv;
        int     peer_addr_len;
        struct  sockaddr_in peer_addr;
        char    authorname[500];
        char    bookname[500];
        char    buf[500];
        struct addrinfo hints, *servinfo, *p;

        // variables and structs for server
        int                     s_sockfd;
        int                     s_bytes;
        char                    s_buf[500];
        // thread_t             s_chld_thr;
        int                     s_rv;
        struct addrinfo         s_hints;
        struct addrinfo         *s_servinfo;
        struct addrinfo         *s_p;
        struct sockaddr_in      s_peer_addr;
        socklen_t               s_peer_addr_len;

////////////////////////////////////////////////////////////
// This section deals with sending data to Server
////////////////////////////////////////////////////////////
        memset(&hints, 0, sizeof (struct addrinfo));
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_protocol = 0;          // any protocol

        if ((rv = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0)
        {
           fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
           exit(1);
        }

        // loop through all the results and connect to the first we can
        for(p = servinfo; p != NULL; p = p->ai_next)
        {
           if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
           {
                perror("socket");
                continue;
           }

           break; // if we get here, connected successfully
        }

        if (p == NULL)
        {
           // looped off the end of the list with no connection
           fprintf(stderr, "failed to connect\n");
           exit(2);
        }

        memcpy(&peer_addr, p->ai_addr, p->ai_addrlen);
        freeaddrinfo(servinfo); // all done with this structure

//////////////////////////////////////////////////////////////////
        sendto(sockfd, "hello", 5, 0, (struct sockaddr *) &peer_addr, sizeof (peer_addr));
///////////////////////////////////////////////////////////////////////////
        memset(s_buf, 0, sizeof (s_buf));
        // read message back from the server
        s_peer_addr_len = sizeof (s_peer_addr);
        s_bytes = recvfrom(sockfd, s_buf, sizeof(s_buf), 0, (struct sockaddr *) &s_peer_addr, &s_peer_addr_len);
        printf("Client received %s\n", s_buf);
}

#8 2013-04-25 02:26 AM

Tera
Guest

Re: Threaded Server is not responding

I further reduced post #7 code as you suggested, but it's only partially working.
1) It is OK if both client and server run on the same machine.
2) It won't work if client runs on a different machine.

Below are the codes:
// Server

// Server code
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <strings.h>
#include <stdlib.h>
#include <thread.h>
#include <netdb.h>
#include <netinet/in.h>

#ifndef SUN_LEN
#define SUN_LEN(su) \
   (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
#endif

int sockfd;
struct  sockaddr_in peer_addr;
socklen_t peer_addr_len;

void* acknowledgement(void* arg);

int main()
{
        int  bytes;
        char buf[500];
        thread_t chld_thr;
        int rv;
        struct addrinfo hints, *servinfo, *p;
        size_t  threadStatus;

        memset(&hints, 0, sizeof (hints));
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_DGRAM;         // SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE; // use my IP address

        if ((rv = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0)
        {
           fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
           exit(1);
        }

        // loop through all the results and bind to the first socket FD found
        for(p = servinfo; p != NULL; p = p->ai_next)
        {
           if ((sockfd = socket(p->ai_family, p->ai_socktype,
            p->ai_protocol)) == -1)
           {
              perror("socket");
              continue;
           }

           if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1)
           {
              close(sockfd);
              perror("bind");
              continue;
           }

           break; // if we get here, connected successfully
        }

        if (p == NULL)
        {
           // looped off the end of the list with no successful bind
           fprintf(stderr, "failed to bind socket\n");
           exit(2);
        }

        freeaddrinfo(servinfo); // all done with this structure

        for(;;)
        {
           memset(buf, 0, sizeof (buf));
           peer_addr_len = sizeof (peer_addr);
           bytes = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *) &peer_addr, &peer_addr_len);
           printf("Server received %s\n", buf);

           // create a new thread to process incoming request
           thr_create(NULL, 0, acknowledgement, (void *) 0, THR_DETACHED, &chld_thr);

//         thr_join(chld_thr, 0 , (void*) &threadStatus);
        }

}

// Send a message back to client to acknowledge that server receives the message
void* acknowledgement(void* arg)
{
   int sd_to_send_back;

   // 1. Create a new socket to send info back to client from server
   sd_to_send_back = socket (AF_INET, SOCK_DGRAM, 0);

   // 3. Send message out of the new socket
   sendto(sd_to_send_back, "Got your message", 16, 0, (struct sockaddr *) &peer_addr, sizeof (peer_addr));

   // 4. Close the new socket
   close(sd_to_send_back);
}

//Client

// client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <stdlib.h>
#include <netdb.h>

#define PORT                    3490

main()
{
        // variables and structs for client
        int     bytes;
        int     sockfd;
        int     rv;
        struct  sockaddr_in peer_addr;
        char    buf[500];
        struct addrinfo hints, *servinfo, *p;
        socklen_t       peer_addr_len;

////////////////////////////////////////////////////////////
// This section deals with sending data to Server
////////////////////////////////////////////////////////////
        memset(&hints, 0, sizeof (struct addrinfo));
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_protocol = 0;          // any protocol

        if ((rv = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0)
        {
           fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
           exit(1);
        }

        // loop through all the results and connect to the first we can
        for(p = servinfo; p != NULL; p = p->ai_next)
        {
           if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
           {
                perror("socket");
                continue;
           }

           break; // if we get here, connected successfully
        }

        if (p == NULL)
        {
           // looped off the end of the list with no connection
           fprintf(stderr, "failed to connect\n");
           exit(2);
        }

        memcpy(&peer_addr, p->ai_addr, p->ai_addrlen);
        freeaddrinfo(servinfo); // all done with this structure

        memcpy(buf, "hello", sizeof(buf));
        buf[499] = '\0';
        sendto(sockfd, buf, 5, 0, (struct sockaddr *) &peer_addr, sizeof (peer_addr));
///////////////////////////////////////////////////////////////////////////
        memset(buf, 0, sizeof (buf));
        // read message back from the server
        peer_addr_len = sizeof (peer_addr);
        recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *) &peer_addr, &peer_addr_len);
        printf("Client received %s\n", buf);
}

#9 2013-04-25 12:29 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,839
Website

Re: Threaded Server is not responding

void *peer_copy;
...
peer_copy = malloc (sizeof (peer_addr));
memcpy (peer_copy, &peer_addr, sizeof (peer_addr));
thr_create (NULL, 0, acknowledgement, peer_copy, THR_DETACHED, &chld_thr);
...
void *acknowledgement (void *arg)
{
    struct sockaddr_in *peer = arg;
    sendto (sockfd, "Got your message", 16, 0, peer, sizeof (*peer));
    free (peer);
}

Offline

#10 2013-04-26 12:10 AM

Tera
Guest

Re: Threaded Server is not responding

Hmmm, I implemented what you suggested, but it won't work for the case where both client/server are on the same machine either.

Here's the code:
-----------------
// Server

// Server code
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <strings.h>
#include <stdlib.h>
#include <thread.h>
#include <netdb.h>
#include <netinet/in.h>

#ifndef SUN_LEN
#define SUN_LEN(su) \
   (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
#endif

int sockfd;
struct  sockaddr_in peer_addr;
socklen_t peer_addr_len;

void* acknowledgement(void* arg);

int main()
{
        int  bytes;
        char buf[500];
        thread_t chld_thr;
        int rv;
        struct addrinfo hints, *servinfo, *p;
        size_t  threadStatus;
        void* peer_copy;

        memset(&hints, 0, sizeof (hints));
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_DGRAM;         // SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE; // use my IP address

        if ((rv = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0)
        {
           fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
           exit(1);
        }

        // loop through all the results and bind to the first socket FD found
        for(p = servinfo; p != NULL; p = p->ai_next)
        {
           if ((sockfd = socket(p->ai_family, p->ai_socktype,
            p->ai_protocol)) == -1)
           {
              perror("socket");
              continue;
           }

           if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1)
           {
              close(sockfd);
              perror("bind");
              continue;
           }

           break; // if we get here, connected successfully
        }

        if (p == NULL)
        {
           // looped off the end of the list with no successful bind
           fprintf(stderr, "failed to bind socket\n");
           exit(2);
        }

        freeaddrinfo(servinfo); // all done with this structure

        for(;;)
        {
           memset(buf, 0, sizeof (buf));
           peer_addr_len = sizeof (peer_addr);
           bytes = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *) &peer_addr, &peer_addr_len);
           printf("Server received %s\n", buf);

           // duplicate a peer_addr
           peer_copy = malloc (sizeof(peer_addr));
           memcpy(peer_copy, &peer_addr, sizeof(peer_addr));
           // create a new thread to process incoming request
           thr_create(NULL, 0, acknowledgement, (void *) 0, THR_DETACHED, &chld_thr);

        }

}

// Send a message back to client to acknowledge that server receives the message
void* acknowledgement(void* arg)
{
   struct sockaddr_in *peer = arg;

   sendto(sockfd, "Got your message", 16, 0, (struct sockaddr *) peer, sizeof (*peer));
   free (peer);
}

// Client

// client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <stdlib.h>
#include <netdb.h>

#define PORT                    3490

int main(int argc, char* argv[])
{
        // variables and structs for client
        char*   host;
        int     bytes;
        int     sockfd;
        int     rv;
        struct  sockaddr_in peer_addr;
        char    buf[500];
        struct addrinfo hints, *servinfo, *p;
        socklen_t       peer_addr_len;


////////////////////////////////////////////////////////////
// This section deals with sending data to Server
////////////////////////////////////////////////////////////
        memset(&hints, 0, sizeof (struct addrinfo));
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_protocol = 0;          // any protocol

        if (argc == 1)
        {
           host = NULL;
        }
        else
        {
           host = "sydney";
        }

        if ((rv = getaddrinfo(host, "3490", &hints, &servinfo)) != 0)
        {
           fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
           exit(1);
        }

        // loop through all the results and connect to the first we can
        for(p = servinfo; p != NULL; p = p->ai_next)
        {
           if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
           {
                perror("socket");
                continue;
           }

           break; // if we get here, connected successfully
        }

        if (p == NULL)
        {
           // looped off the end of the list with no connection
           fprintf(stderr, "failed to connect\n");
           exit(2);
        }

        memcpy(&peer_addr, p->ai_addr, p->ai_addrlen);
        freeaddrinfo(servinfo); // all done with this structure

        memcpy(buf, "hello", sizeof(buf));
        buf[499] = '\0';
        sendto(sockfd, buf, 5, 0, (struct sockaddr *) &peer_addr, sizeof (peer_addr));
///////////////////////////////////////////////////////////////////////////
        memset(buf, 0, sizeof (buf));
        // read message back from the server
        peer_addr_len = sizeof (peer_addr);
        recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *) &peer_addr, &peer_addr_len);
        printf("Client received %s\n", buf);
}

(Will temporarily lose the access to unix machine for awhile after this, hopefully, I can pick up this mini self-learning DYI very soon...)

#11 2013-04-26 11:57 AM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,839
Website

Re: Threaded Server is not responding

if (argc == 1)
        {
           host = NULL;
        }
        else
        {
           host = "sydney";
        }

Offline

#12 2013-04-27 09:11 AM

Tera
Guest

Re: Threaded Server is not responding

Thank you, Rob.

Board footer

Powered by FluxBB