epoll issue: tunneling and multi-threading - multithreading

I encounter this problem while trying to do TCP tunnelling between two threads.
Thread 1
listen at Port
accept
then add the sock after accept to epoll_ctl
while (1)
epoll_wait
read whatever from Port to remote (tunnelling)
Thread 2
connect to Port
if connected
communicate...
What I actually observe is: while Thread 2 is blocked on connect, Thread 1 has no chance to run epoll_wait and send the connect info to the remote. Thus both threads cannot make progress.
One possible solution is to use parent-child processes instead of multi-threading. But before I switch to that, could it still be done with multi-threading? I think what it is needed here is some kind of interrupt thing than just polling. Right?
Thank you for the insight.

You can add server side socket descriptor into epoll_ctl. But I'm curious that if thread2 blocked on connection, what information you need to send to server? Thanks for your hint.

Related

TCP socket: Blocking or non-blocking?

I am writing a PC application that will connect with TCP to multiple micro-controller boards. The micro-controller boards are listening and the PC app connecting to each of them as a client.
There can be up to up to about 50 boards depending on configuration, and it is not clear to me if it is best to create all these sockets as blocking in individual threads waiting at recv() or make the sockets non-blocking and use select() to check for incoming data one socket at the time.
So is up to 50 threads of blocking recv() OK, or is it better to check one socket at the time with select()?
Info: Data is almost entirely coming from the micro-controller boards and the rate can vary from essentially nothing to max. of the network.
Thanks...

server.listen(5) vs multithreading in socket programming

I am working on socket programming in python. I am a bit confused with the concept of s.listen(5) and multithreading.
As I know, s.listen(5) is used so that the server can listen upto 5 clients.
And multithreading is also used so that server can get connected to many clients.
Please explain me in which condition we do use multithreading?
Thanks in advance
You will need to use multithreading to handle multiple clients. When you accept a connection you receive a new socket instance that represents the connection with that new client. Now lets suppose you are making a chat and you need to receive the data from one client and send it to all connected clients, if you are not using multithreading you will need to implement a non-performatic logic using a single process loop to walk your connected clients reading each one and after all send to them the data, but you will have another problem because the listen function creates an IO interruption that waits until a new client try to connect if you don't use non-block socket. It's all about architecture, performance and good practices.
A good reading about multithreading follow this link https://techdifferences.com/difference-between-multiprocessing-and-multithreading.html.
As I know, s.listen(5) is used so that the server can listen upto 5 clients.
No. s.listen(5) declares a backlog of size 5. Than means that the listening socket will let 5 connection requests in pending stated before they are accepted. Each time a connection request is accepted it is no longer in the pending backlog. So there is no limit (other than the server resources) to the number of accepted connections.
A common use of multithreading is to start a new thread after a connection has been accepted to process that connection. An alternative is to use select on a single thread to process all the connections in the same thread. It used to be the rule before multithreading became common, but it can lead to more complex programs

Avoiding connection refused error for multiple sockets in C

Just a quick background. I am willing to open two sockets per thread of the application.The main thread has the accept() call to accept a TCP connection. There are three other threads and all of them also have an accept(). The problem is sometimes in multithreaded environment, the client tries to connect before the accept call of the server in a child thread which results in "connection refused" error. The client doesn't know when the server is ready to connect
I do not want the main thread socket to be sending any control information to the client like "You can now connect to the server". To avoid this, I have two approaches in my mind
1. To set a max counter(attempt) at the client side to connect to the server before exiting with connection refused error.
2. A separate thread whose only function is to accept connections at server side as a common accept function for all the thread connections except for the main thread.
Would really appreciate to know if there is any other approach. Thanks
Connection refused is not because you're calling accept late, it's because you're calling listen late. Make sure you call listen before any connect calls (you can check with strace). This probably requires that you listen before you spawn any children.
After you call listen on a socket incoming connections will queue until you call accept. At some point the not-yet-accepted connections can get dropped but this shouldn't occur with only 2 or 3 sockets.
If this is unix you can just use pipe2 or socketpair to create a pair of connected pipes/unix domain sockets with a lot less code. Of course, you need to do this before spawning the child thread and pass one end to the child.

Understanding BSD interface

I'm trying to understand how the events in a BSD socket interface translate to the state of a TCP Connection. In particular, I'm trying to understand at what stage in the connection process accept() returns on the server side
client sends SYN
server sends SYN+ACK
client sends ACK
In which one of these steps does accept() return?
accept returns when the connection is complete. The connection is complete after the client sends his ACK.
accept gives you a socket on which you can communicate. Of course you know, you can't communicate until the connection is established. And the connection can't be established before the handshake.
It wouldn't make sense to return before the client sens his ACK. It is entirely possible he won't say anything after the initial SYN.
The TCP/IP stack code in the kernel normally[1] completes the three-way handshake entirely without intervention from any user space code. The three steps you list all happen before accept() returns. Indeed, they may happen before accept() is even called!
When you tell the stack to listen() for connections on a particular TCP port, you pass a backlog parameter, which tells the kernel how many connections it can silently accept on behalf of your program at once. It is this queue that is being used when the kernel automatically accepts new connection requests, and there that they are held until your program gets around to accept()ing them. When there is one or more connections in the listen backlog queue when you call accept(), all that happens is that the oldest is removed from the queue and bound to a new socket.[2]
In other words, if your program calls listen(sd, 5), then goes into an infinite do-nothing loop so that it never calls accept(), five concurrent client connection requests will succeed, from the clients' point of view. A sixth connection request will get stalled on the first SYN packet until either the program owning the TCP port calls accept() or one of the other clients drops its connection.
[1] Firewall and other stack modifications can change this behavior, of course. I am speaking here only of default BSD sockets stack behavior.
[2] If there are no connections waiting in the backlog when you call accept(), it blocks by default, unless the listener socket was set to non-blocking, in which case it returns -1 and errno is EWOULDBLOCK.

Socket fd in multithreading

Is it ok to use same socket fd in multiple threads ? (over linux)
It depends on what you expect to happen, but yes you can. If you are reading UDP packets that are each a complete message this can work well. If you are reading data streams from TCP this will probably not work well.
You can have multiple threads accepting incoming connections on a socket and that can work pretty well as each thread gets one connection.
You will run into concurrency problems trying to send() or recv() (SOCK_STREAM) from multiple threads. You should use a critical section or some other means of creating serial access to send() and recv().
One standard thing to do with threads is to have the master listen() & accept(), then pass off the socket to a client thread that sends/receives/processes from that one socket. The client thread is responsible for calling close() or shutdown().

Resources