469,909 Members | 1,737 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,909 developers. It's quick & easy.

Linux Sockets and POSIX threads example

Hi,
I am trying to encapsulate Linux sockets and POSIX threads in C++ classes (I work in Knoppix, using KDevelop). Since sockets and threads are new to me, I searched for example code and found the following:

Expand|Select|Wrap|Line Numbers
  1.  
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <errno.h>
  6. #include <netdb.h>
  7. #include <signal.h>
  8. #include <fcntl.h>
  9. #include <netinet/ip.h>
  10. #include <pthread.h>
  11.  
  12. struct sockaddr_in getipa(const char*, int);
  13. void printerror(const char*);
  14.  
  15. void* runclient(void*);
  16. void* runserver(void*);
  17.  
  18. int main(){
  19.     pthread_t server;
  20.     pthread_t client;
  21.  
  22.     if(pthread_create(&server, NULL, runserver, NULL) != 0){
  23.         puts("Could not create server thread");
  24.  
  25.         return EXIT_FAILURE;
  26.     }
  27.  
  28.     if(pthread_create(&client, NULL, runclient, NULL) != 0){
  29.         puts("Could not create client thread");
  30.  
  31.         return EXIT_FAILURE;
  32.     }
  33.  
  34.     pthread_join(server, NULL);
  35.     pthread_join(client, NULL);
  36.  
  37.     return EXIT_SUCCESS;
  38. }
  39.  
  40. struct sockaddr_in getipa(const char* hostname, int port){
  41.     struct sockaddr_in ipa;
  42.     ipa.sin_family = AF_INET;
  43.     ipa.sin_port = htons(port);
  44.  
  45.     struct hostent* localhost = gethostbyname(hostname);
  46.     if(!localhost){
  47.         printerror("resolveing localhost");
  48.  
  49.         return ipa;
  50.     }
  51.  
  52.     char* addr = localhost->h_addr_list[0];
  53.     memcpy(&ipa.sin_addr.s_addr, addr, sizeof addr);
  54.  
  55.     return ipa;
  56. }
  57.  
  58. void printerror(const char* action){
  59.     int errnum = errno;
  60.     errno = 0;
  61.  
  62.     if(errnum > 0){
  63.         printf("An error occured while %s.nError code: %inError description: %sn",
  64.                 action, errnum, strerror(errnum));
  65.     }else if(h_errno > 0){
  66.         printf("An error occured while %s.nError code: %inError description: %sn",
  67.                 action, h_errno, hstrerror(h_errno));
  68.  
  69.         h_errno = 0;
  70.     }else{
  71.         printf("An error occured while %s.n There is no error data.n", action);
  72.     }
  73. }
  74.  
  75. void* runserver(void* context){
  76.     struct protoent* tcp;
  77.     tcp = getprotobyname("tcp");
  78.  
  79.     int sfd = socket(PF_INET, SOCK_STREAM, tcp->p_proto);
  80.     if(sfd == -1){
  81.         printerror("createing a tcp socket");
  82.  
  83.         return NULL;
  84.     }
  85.  
  86.     struct sockaddr_in isa = getipa("localhost", 1025);
  87.  
  88.     if(bind(sfd, (struct sockaddr*)&isa, sizeof isa) == -1){
  89.         printerror("binding socket to IP address");
  90.  
  91.         return NULL;
  92.     }
  93.  
  94.     if(listen(sfd, 1) == -1){
  95.         printerror("setting socket to listen");
  96.  
  97.         return NULL;
  98.     }
  99.  
  100.     int cfd = accept(sfd, NULL, NULL);
  101.  
  102.     if(cfd == -1){
  103.         if(errno == EAGAIN || errno == EWOULDBLOCK){
  104.             puts("SIGIO recieved for listen socket, but don't know why.");
  105.         }else{
  106.             printerror("accepting a connection");
  107.  
  108.             return NULL;
  109.         }
  110.     }
  111.  
  112.     char msg[] = "Message to be sent";
  113.  
  114.     if(send(cfd, (void*) msg, sizeof msg, MSG_NOSIGNAL) == -1){
  115.         printerror("sending message to client");
  116.     }
  117.  
  118.     shutdown(cfd, SHUT_RDWR);
  119.  
  120.     return NULL;
  121. }
  122.  
  123. void* runclient(void* context){
  124.     struct protoent* tcp;
  125.     tcp = getprotobyname("tcp");
  126.  
  127.     int sfd = socket(PF_INET, SOCK_STREAM, tcp->p_proto);
  128.     if(sfd == -1){
  129.         printerror("createing a tcp socket");
  130.  
  131.         return NULL;
  132.     }
  133.  
  134.     struct sockaddr_in isa = getipa("localhost", 1025);
  135.  
  136.     if(connect(sfd, (struct sockaddr*)&isa, sizeof isa) == -1){
  137.         printerror("connecting to server");
  138.  
  139.         return NULL;
  140.     }
  141.  
  142.     char buff[255];
  143.     ssize_t size = recv(sfd, (void*)buff, sizeof buff, MSG_WAITALL);
  144.  
  145.     if(size == -1){
  146.         printerror("recieving data from server");
  147.     }else{
  148.         buff[size] = '';
  149.  
  150.         puts(buff);
  151.     }
  152.  
  153.     shutdown(sfd, SHUT_RDWR);
  154.  
  155.     return NULL;
  156. }
  157.  
  158.  
This is C code, but I thought, "If I get this working, encapsulating in classes will be easy". The problem is that this code works fine only the first run; afterwards, it cannot resolve the IP address. Which could be the reason?
Oct 30 '06 #1
2 23926
I discovered that changing the port number and recompiling allows for another succesful run (only once, like before). Therefore, it seems to me that ports are not freed after the program finishes. How can I do that?
Oct 31 '06 #2
Well, I figured it out myself: Even if you close a socket correctly, it takes a maximum of 60 seconds for it to be freed: I ran the first time OK; then I waited a minute, ran again and had no problems. So that's it, I hope this helps someone.
Nov 1 '06 #3

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

reply views Thread by Al Tobey | last post: by
2 posts views Thread by shyamal | last post: by
1 post views Thread by lineak | last post: by
15 posts views Thread by kernel.lover | last post: by
2 posts views Thread by Stressed Out Developer | last post: by
7 posts views Thread by Sourav | last post: by
reply views Thread by Salome Sato | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.