3

I created a TCP client application and decided to handle incoming data with a new thread using the pthread library in c.

However, I read somewhere that unexpected things could happen when multiple threads try to write to the same file descriptor for a socket connection.

what is the best approach to ensure these 'unexpected things' don't happen.

Is there even a need to using threads in the first place?

NB: My decision to use threads was to prevent any blocking operations.

Oladipo Olasemo
  • 2,010
  • 24
  • 31
  • 2
    The best approach is to make sure that only one thread reads/writes the socket. NB: before deciding to use threads, you need to explain why blocking is undesirable. – user3386109 Dec 28 '16 at 01:23
  • Vote to close: too broad – Stargateur Dec 28 '16 at 01:28
  • The application is a USSD application - Unstructured Supplementary Service Data. It will serve multiple users dialing a short code sometimes almost at the same time. The USSD gateway has a timeout in effect and it is required that client applications provide a response within this time frame. User experience will drastically be affected when they have to wait and sometimes their requests may time out. – Oladipo Olasemo Dec 28 '16 at 01:29
  • 2
    @OladipoOlasemo Do you know [`select()`](http://man7.org/linux/man-pages/man2/select.2.html)? – Stargateur Dec 28 '16 at 01:31
  • Yes. I read about it. Not sure how to implement it in actual code. – Oladipo Olasemo Dec 28 '16 at 01:31
  • [facil.io](http://facil.io) is designed for servers, but you can use it for a client as well. It will provide you with an evented design, allowing for both multi-threaded and single threaded non-blocking operations... there are others out there that will make your life easier. – Myst Dec 28 '16 at 01:58
  • You can have as many threads as you like writing to a socket, but that doesn't in any way eliminate blocking. If one blocks they will all block. Unclear what you're asking. – user207421 Dec 28 '16 at 02:42
  • I noticed the client app closes the socket randomly. I have not been able to find out why. I read somewhere that it could be a direct result of multiple threads writing to the socket at the same time - sometimes it works, sometimes it doesn't - when it doesn't I assume the app crashed and socket closed. but i have no direct evidence for this. Is it okay to have multiple threads writing to a socket without using a queue of some sort or perhaps multiplexing? – Oladipo Olasemo Dec 28 '16 at 02:49
  • It's OK as long as you don't mind possible data interleaving, but it doesn't solve your actual problem. You should certainly know why your own code closes a socket. – user207421 Dec 28 '16 at 03:48
  • *Why* don't you want to use blocking operations, or lock the one socket? You're communicating across a network where the latencies are significantly larger than any performance impact on your application. And there are almost certainly blocks/locks in the socket implementation anyway. – Andrew Henle Dec 28 '16 at 04:05
  • @EJP I totally agree. I must must know why it closes a socket – Oladipo Olasemo Dec 28 '16 at 04:20
  • Your code closes the socket: you only have to read the code to find out why. Are you using the right words? Do you perhaps mean that it randomly encounters *connection* resets? – user207421 Dec 28 '16 at 05:26

3 Answers3

1

To avoid blocking, you should research asynchronous operations. You can either learn how your particularly platform handles them, or use a library, such as ASIO (https://think-async.com/) which will handle it for you.

user207421
  • 305,947
  • 44
  • 307
  • 483
Mikel F
  • 3,567
  • 1
  • 21
  • 33
1

Might I recommend using libuv? It's highly maintained (core of node.js) and cross-platform.

Also, you should not use select() that's old school. If you did it yourself you should use epoll() on Linux. It scales much better.

You should only have one writer thread ever. That thread should write when the socket is not busy.

Checkout libuv - it handles all this messiness for you but still keeps you close to the metal. https://nikhilm.github.io/uvbook/networking.html

My approach on stuff like this is to typically have one writer thread, and a fast reader callback, usually just allocating memory for the incoming data, which then just delegates to 1 or more processing threads. If you want it fast avoid memcpy at all cost, and allocate a big buffer to began with.

EdH
  • 3,194
  • 3
  • 21
  • 23
-2
  • Yes, you need to create threads if you want to do anything else while waiting for incoming TCP data

  • Yes, you need to take care of unexpected things that may happen in a multi threaded programs

You should use Mutexes to prevent the so called unexpected things. the pthread library you're using to create threads also contains synchronization primitives.

A sample program may look like this

pthread_mutex_t tcp_lock;

void ThreadFunction()
{
        pthread_mutex_lock(&tcp_lock);
        // Do your stuffs 
        pthread_mutex_unlock(&tcp_lock);
}

int MainThread()
{
    pthread_mutex_lock(&tcp_lock);
    // Do your stuffs
    pthread_mutex_unlock(&tcp_lock);
}
Daksh Gupta
  • 7,554
  • 2
  • 25
  • 36
  • 3
    "Yes, you need to create threads if you want to do anything else while waiting for incoming TCP data", no. man select, poll. They are many way to do a server, thread is one of them. – Stargateur Dec 28 '16 at 03:45
  • No, you don't 'need to create threads if you want to do anything else while waiting for incoming TCP data'. You can use non-blocking or multiplexed or asynchronous I/O. – user207421 Dec 28 '16 at 03:50
  • select, poll , epoll are the best mechanism if you don't want to block your thread when there is no data in socket. – Sanjeevkumar M Nov 19 '20 at 04:37