Find the answer to your Linux question:
Results 1 to 4 of 4
I have a client - server tcp communication. The client transmits a message, server reads it, transmits something else back. The problem is now back on the client's side at ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    May 2009
    Posts
    8

    read TCP socket problem


    I have a client - server tcp communication. The client transmits a message, server reads it, transmits something else back. The problem is now back on the client's side at the reception of a message. There are 2 threads handling the transmition and reception to/from client. The one which is responsible for the reception is not working. (I know I should read in a while loop to be sure I get all the message, I will take care of that later, since in my opinion the problem is somewhere else at the moment)

    Here is the code:


    Code:
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    
    if (connect(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
             Die("Failed to connect with server");
         }
    
    FD_ZERO( &read_set );
    FD_SET( sock, &read_set );
    
    ret = select(1, &read_set, NULL, NULL, &tv);
    
    if (ret == -1) perror("select()");
    else if (ret)
            {
                  fprintf(stdout,"Data is available now.\n");
                  bytes=read(sock, buffer, 8,0);
                  fprintf(stdout, "bytes: %i\n", bytes);
             }
             else
                   printf("No data.\n");
    If this code follows up immediately after the client sends something (so in the same thread) it works just fine, and there is continuous communication between client and server as desired. But if I want to have 2 different threads for sending and receiving it doesn't work anymore. Can't figure out why!

    Capturing with Wireshark shows that the message is received. But my application doesn't receive it.

    strace on the process:

    restart_syscall(<... resuming interrupted call ...>) = 1
    ioctl(7, FIONREAD, [46]) = 0
    recvfrom(7, "\0\1\10\0\6\4\0\2\0\220g\0O\233\300\250\1\24\0\20 0\310"..., 46, 0, {sa_family=AF_PACKET, proto=0x806, if4, pkttype=PACKET_HOST, addr(6)={1, 009067004f9b}, [18]) = 46
    poll(

    Any ideas about what it's actually happening and how I can fix it?

  2. #2
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,512
    The read function only has 3 arguments (fd, buffer, size). You are calling it with four. However, I doubt that is your problem. You probably need to do the connecting and selecting in the main program, dispatching the read/write operations to the appropriate threads. However, I don't think you can send and receive on the same socket at the same time. I'm not sure about that since I haven't tried what you are doing - honestly I never needed to, even when dealing with big bandwidth applications such as stock quoting applications that handled huge amounts of data from multiple market data feeds. Remember the KISS principal. That will hold you in good stead. Only opt for more complex (threaded) application code when a well-designed application cannot handle the processing latency. If you aren't running a multi-core or SMP system, then threads buy you very little, at a huge development cost.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  3. #3
    Just Joined!
    Join Date
    May 2009
    Posts
    8
    Thanks for your quick reply!

    The fourth argument of the read() comes from switching between read() and recv() (in the hope that the other call brings more, although I knew it actually wouldn't). Forgot to delete it, sorry!

    As far as I read, sockets are thread safe, and if I got it right, they could manage both sending and receiving. But not being 100% sure, I went on implementing exactly the step which you also advised me to: try sending on one port and receiving on another, but I got stuck in creating a new socket on server for transmition (socket() returns 0 and I ran out of ideas how to fix this, not that I had so many... ). So I decided to go back to the previous code. I thought I am not receiving it right back to the client, I should implement the comunication in one way on one port, and the other way, on another port. I'm working on it at the moment...

    Could you explain a bit more the last part of your post? Do you mean that using threads will take too many resources?

  4. #4
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,512
    Robust threaded applications are very difficult to write. There are MANY opportunities for race conditions and resource contention and deadlocks. Many person-years of effort has been wasted debugging these applications. Where threads really work well is when you need to handle a number of concurrent connections as efficiently as possible. In such cases (web or database servers for instance), each thread manages a separate connection and process all i/o requests in a single thread's context. They might have additional worker threads that do no I/O (or only I/O from normal file descriptors such as stdin and stdout), but all the I/O for a single connection is handled by the same thread. It's just easier and safer to do it that way.

    Use select with both read and write fd sets. The worker thread that needs to write data will put it in a buffer accessible by the main thread, which will send it when the socket is able to handle the data. Likewise, when it knows that there is data to read, it will read the data and post it to a buffer the worker thread that processes incoming data can access. Usually a semaphore will be used to signal the worker threads that they can access the read or write buffers. So, the worker threads wait on the semaphore, and when woken up, do whatever is necessary. The main thread for each connection then becomes a traffic cop, handling the socket traffic and telling each worker thread when they can go.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •