Thread: Socket wont close

  1. #1
    Registered User
    Join Date
    Nov 2010
    Posts
    2

    Socket wont close

    Hi,
    I am trying to create a simple tcp client for sending a stucture. I've tried the separate client and server programs, but I am trying to merge it all into one, so a single client can read and also send.
    Code:
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <glib.h>
    #include <pthread.h>
    #include <assert.h>
    
    //non standard headers
    
    #include "message.h"
    #include "config.h"
    
      int	       list_s;
      int           sock;
      int		conn_s;
      struct	sockaddr_in servaddr;
      ssize_t bytes_encoded, bytes_sent, bytes, lbytes;
      char   buffer[MAX_BUFFER];
    
    void *message_listener()
    {
    
      
      if((list_s = socket(AF_INET, SOCK_STREAM,0)) < 0)
      {
     
        fprintf(stderr, "Error: Can not create listening socket.\n");
        exit(EXIT_FAILURE);
      }
    
      memset(&servaddr, 0, sizeof(servaddr));
      servaddr.sin_family		= AF_INET;
      servaddr.sin_addr.s_addr	= htonl(INADDR_ANY);
      servaddr.sin_port		= htons(HOST_PORT);
    
      g_print("Starting Listener\n");
    
      if(bind(list_s, (struct sockaddr *) &servaddr, sizeof(servaddr))<0)
      {
    
        fprintf(stderr, "Error: Can not bind socket.\n");
        exit(EXIT_FAILURE);
      }
    
      if (listen(list_s, 5) <0)
      {
    
        fprintf(stderr, "Error: Can not call listen()\n");
        exit(EXIT_FAILURE);
      }
    
      g_print("Listener started\n");
    
      if ((conn_s = accept(list_s, NULL, NULL))<0)
      {
    
        fprintf(stderr, "Error: Can not call accept()\n");
        exit(EXIT_FAILURE);
      }
      Message *mess;
    
      mess = alloc_blank_message();
    
      lbytes = read(conn_s, buffer, MAX_BUFFER);
      printf("bytes recieved= %d\n", lbytes);
      deserialize_message(buffer, mess);
      g_print("Message: %s\n", mess->message);
    
      if (close(conn_s)<0);
      {
    
        fprintf(stderr, "Error: can not close() on listener\n");
        exit(EXIT_FAILURE);
      }
    
      
      free_message(mess);
      pthread_exit(NULL);
      return NULL;
    }
    
    void *sendmessage()
    {
     
      Message *mess1;
    
      mess1 = make_message(1);
      set_message_string(mess1, "test message");
    
      if ((sock = socket(AF_INET, SOCK_STREAM, 0)) <0)
      {
        
        fprintf(stderr, "Error: Can not create socket.\n");
        exit(EXIT_FAILURE);
      }
    
      memset(&servaddr, 0, sizeof(servaddr));
      servaddr.sin_family	   = AF_INET;
      servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
      servaddr.sin_port	   = htons(HOST_PORT);
    
      if(connect(sock, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
      {
     
        fprintf(stderr, "Error: Can not call connect()\n");
        exit(EXIT_FAILURE);
      }
    
      bytes_encoded = serialize_message(buffer, mess1);
      g_print("Bytes encoded = %d\n", bytes_encoded);
      
      bytes_sent = send(sock, buffer, bytes_encoded, 0);
    
      if(bytes_sent != bytes_encoded)
      {
    
        fprintf(stderr, "Error: Can not call send()\n");
        exit(EXIT_FAILURE);
      }
      
      if( close(sock) < 0 )
      {
      
        fprintf(stderr, "Error: Can not call close() on sender\n");
        exit(EXIT_FAILURE);
      }
    
      free_message(mess1);
      pthread_exit(NULL);
    }
    
    int main(int argc, char *arg[])
    {
      
      
      pthread_t messageListen_thread;
      void *exit_status;
      pthread_t sender_thread;
      
      pthread_create(&messageListen_thread, NULL, message_listener, NULL);
      
      g_print("Started Listener Thread\n");
      pthread_create(&sender_thread, NULL, sendmessage, NULL);
      pthread_join(messageListen_thread, &exit_status);
      pthread_join(sender_thread, &exit_status);
      
      return 0;
     }
    I assumed that to read and send I would need threads, but I am finding that after the structure has been sent, the socket can not close().

    Any ideas what might be up?

    thanks

  2. #2
    Registered User matrixx333's Avatar
    Join Date
    Mar 2009
    Posts
    67
    Sounds like you need non-blocking sockets:

    Blocking vs. non-blocking sockets
    Slightly Advanced Techniques

    Hope this helps!

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    You should call shutdown() before you close a send/receive (but not a listener) socket. That will (mostly) ensure a graceful disconnection. Also, the accept()/connect() calls should be placed inside of loops, for efficiency's sake (no sense in creating a new thread for each connection*)...

    * Depending on how responsive you need them to be, of course. You can always launch a new thread from a pool (from within those loops that I mentioned earlier), if necessary.
    Last edited by Sebastiani; 11-15-2010 at 10:35 AM.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #4
    Registered User
    Join Date
    Nov 2010
    Posts
    2
    thanks guys, I added the shutdown method (though Im interested why I shouldnt use it on a listening socket), but I found I was stupid enough to accidentally had a ; where there shouldnt be:
    Code:
    if (close(conn_s) < 0);
      {
    
        fprintf(stderr, "Error: can not close() on listener\n");
        exit(EXIT_FAILURE);
      }
    It now seems to be working, though sometimes it refuses to connect(). Other than the loop which I should use (thanks for the tip!) does the rest look ok? I wasn't sure if I should create two sockets (one for listener, one for sender) or if I could use one socket for both?

    Thanks for your help!

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by deankramer99 View Post
    I wasn't sure if I should create two sockets (one for listener, one for sender) or if I could use one socket for both?
    No, you can't use the same socket for both purposes.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Why the local socket program occur core dump?
    By chenayang in forum Linux Programming
    Replies: 16
    Last Post: 08-16-2010, 08:39 AM
  2. Function call from another .c module
    By Ali.B in forum C Programming
    Replies: 14
    Last Post: 08-03-2009, 11:45 AM
  3. socket programming question, closing sockets...
    By ursula in forum Networking/Device Communication
    Replies: 2
    Last Post: 05-31-2009, 05:17 PM
  4. when to close a socket
    By Wisefool in forum Networking/Device Communication
    Replies: 5
    Last Post: 11-02-2003, 10:33 AM
  5. Ghost in the CD Drive
    By Natase in forum A Brief History of Cprogramming.com
    Replies: 17
    Last Post: 10-12-2001, 05:38 PM