Connecting Tech Pros Worldwide Forums | Help | Site Map

socket and pthread

Newbie
 
Join Date: Oct 2008
Posts: 15
#1: Sep 28 '09
Hi all.
I have a socket. I want to create two threads, one is to read from socket, and another is to write to socket. However, I want these two threads to be able to share the same data, so I created a mutex to lock the resource.
I don't know what happens with my two threads, but it always quits after it did some tasks.
Expand|Select|Wrap|Line Numbers
  1. #include "camel.h"
  2. #include "irc.h" 
  3.  
  4. pthread_t         gtid;
  5. pthread_mutex_t   gMutex;
  6.  
  7. // The shared resource between reading and writing thread
  8. char              gSntBuffer[MAX_SIZE_BUFFER];
  9.  
  10. void*
  11. SendRequest( INPUT void* pArg)
  12. {
  13.     int  lsockfd;
  14.     DBGSTR(3,
  15.            STATUS_SUCCESS,
  16.            "FUNCTION ENTRY",
  17.            "")
  18.     lsockfd = (int)pArg;       
  19.     while(1)
  20.     {
  21.         pthread_mutex_lock(&gMutex);
  22.  
  23.         if (gSntBuffer)
  24.         {
  25. #ifdef DBG
  26.             printf("Snt Buffer : %s\n", gSntBuffer);
  27. #endif
  28.             write(lsockfd, gSntBuffer, MAX_SIZE_BUFFER);
  29.         }
  30.  
  31.         pthread_mutex_unlock(&gMutex);
  32.     }
  33.     DBGSTR(3,
  34.            STATUS_SUCCESS,
  35.            "FUNCTION EXIT",
  36.            "")        
  37. }
  38.  
  39. void*
  40. ReceiveReply( INPUT void* pArg)
  41. {
  42.     int   lsockfd = (int)pArg;
  43.     char  lRcvBuffer[MAX_SIZE_BUFFER];
  44.     int   lBytes  = 0;
  45.     DBGSTR(3,
  46.            STATUS_SUCCESS,
  47.            "FUNCTION ENTRY",
  48.            "")    
  49.     while(1)
  50.     {
  51.         lBytes = read(lsockfd, lRcvBuffer, MAX_SIZE_BUFFER);
  52. #ifdef DBG
  53.         printf("Rcv Buffer : %s", lRcvBuffer);
  54. #endif
  55.         // here I have to filter the lRcvBuffer and 
  56.         // then write something back to socket by filling 
  57.         // the gSntBuffer only and let the SendRequest()
  58.         // do the rest of the job.
  59.         // 
  60.  
  61.         // .... CODE HERE
  62.     }
  63.     DBGSTR(3,
  64.            STATUS_SUCCESS,
  65.            "FUNCTION EXIT",
  66.            "")        
  67. }
  68.  
  69. tRtnCode
  70. ConnectIRC( INPUT tProfile profile )
  71. {
  72.     int                lsockfd;
  73.     struct sockaddr_in lservaddr;
  74.     int                lrvalue;
  75.  
  76.     pthread_attr_t     lattr;
  77.  
  78.     DBGSTR(3,
  79.            STATUS_SUCCESS,
  80.            "FUNCTION ENTRY",
  81.            "")           
  82.  
  83.     memset(&lservaddr, 0, sizeof(lservaddr));
  84.     lservaddr.sin_family      = AF_INET;
  85.     lservaddr.sin_port        = htons(profile.port);
  86.     lservaddr.sin_addr.s_addr = inet_addr(profile.server);
  87.  
  88.     if (0 >= (lsockfd = socket(AF_INET, SOCK_STREAM,0)))
  89.     {
  90.         DBGINT(1,
  91.                ERROR_SOCK_CANNOT_CREATE,
  92.                "lsockfd = ",
  93.                lsockfd)
  94.         return (ERROR_SOCK_CANNOT_CREATE);
  95.     }
  96.  
  97.     printf("SendRequest() : losckfd = %d\n", lsockfd);
  98.  
  99.     if (0 < (lrvalue = connect(lsockfd, (struct sockaddr*)&lservaddr, sizeof(lservaddr))))
  100.     {
  101.         DBGINT(1,
  102.                ERROR_SOCK_CANNOT_CONNECT,
  103.                "connect() returns ",
  104.                lrvalue)
  105.         return (ERROR_SOCK_CANNOT_CONNECT);
  106.     }
  107.  
  108.     // set attributes
  109.     pthread_attr_init(&lattr);
  110.     pthread_attr_setdetachstate(&lattr, PTHREAD_CREATE_DETACHED);
  111.     pthread_attr_setscope(&lattr, PTHREAD_SCOPE_SYSTEM);
  112.  
  113.     // init mutex
  114.     pthread_mutex_init(gMutex, NULL);
  115.     pthread_mutex_lock(&gMutex);
  116.  
  117.     snprintf(gSntBuffer, 
  118.              MAX_SIZE_BUFFER,
  119.              IRC_USER,
  120.              profile.username,
  121.              "",
  122.              "",
  123.              profile.fullname,
  124.              profile.nickname);
  125.  
  126.     pthread_mutex_unlock(&gMutex);
  127.  
  128.     // create 2 threads
  129.     // - read data
  130.     // - write data
  131.  
  132.     pthread_create(&gtid, &lattr, SendRequest,  (void*)lsockfd);
  133.     pthread_create(&gtid, &lattr, ReceiveReply, (void*)lsockfd);
  134.  
  135.     DBGSTR(3,
  136.            STATUS_SUCCESS,
  137.            "FUNCTION EXIT",
  138.            "")
  139. }

Banfa's Avatar
Administrator
 
Join Date: Feb 2006
Location: South West UK
Posts: 6,210
#2: Sep 28 '09

re: socket and pthread


It's not in the posted code but you need to ensure that main does not exit (i.e. return) until your threads have finished.
gpraghuram's Avatar
Expert
 
Join Date: Mar 2007
Location: Chennai
Posts: 1,258
#3: Sep 29 '09

re: socket and pthread


HI,
R u creating the thread a sdetached or attached thread?
If you are creating it as a attcahed thred the call pthread_join() and return after the call.

Raghu
Newbie
 
Join Date: Oct 2008
Posts: 15
#4: Sep 29 '09

re: socket and pthread


Thank gpraghuram
oh yes....you're right. I forget to set the attribute to be JOINABLE, and join them to the main thread, so that the main thread could wait for all of the child threads to be terminated.
Newbie
 
Join Date: Oct 2008
Posts: 15
#5: Sep 29 '09

re: socket and pthread


Anyway, how about the same resource shared by two threads ?
I have to use the pthread_mutex_t to lock it right ?
I am not sure when to lock the resource. Let's say, there are 2 threads, one is to write data, and another is to read data, so in either reading or writing, we lock the resource ? or we lock only when we write ?
Banfa's Avatar
Administrator
 
Join Date: Feb 2006
Location: South West UK
Posts: 6,210
#6: Sep 29 '09

re: socket and pthread


Lock for both reading and writing but for efficiency keep the lock for as short a time as possible.

If you don't lock for reading the writing thread may change the data in the middle of you reading it which could produce very strange results.
Reply