I'm very new in the network programming, i writed an IOCP network for Windows with c++, but i have a big contradiction;
many threads can send to same socket, so i used a lock before WSASend because i read about WSASend is not thread-safe, my question is, a thread calls WSASend and while send operation is in progress, if another thread calls WSASend again, what do i need to do?
Should i call WSASend for the second call, or do i need to add a queue and when its completed, send the cache?
What is the best performance tricks for iocp?
Related
I'd like to write server (TCP/IP) and i have some questions because I am not sure if I think properly.
I need a server with only one thread. I need to read and write data to some clients. I'd like to use async_accept, async_write, async_read etc. from boost::asio.
Is it OK in case of calling async_write for different clients in the same time? What if my program calls async_write for one client and before handler is called it calls async_write for another client?
The same question about async_read.
Isn't it problem?
Is it warranted (in this case) that callback from first calling async_write will be called before callback from second async_write?
What if some callback (handler) takes long time? Other callbacks just wait in a stack until this one will be finished? And if this callback never ends another callbacks will be never executed? Am I right?
There is no problem with overlapping async read and write calls to different sockets. I would recommend you give each connection its own strand so that things won't break in the future should you decide to add TLS support or use more than one thread. The completion handlers can be called in any order, depending on the order in which the operations actually complete. Of course, you cannot have two async read operations or two async write operations on the same connection at the same time.
No, it isn't a problem.
No, it isn't warranted.
No, callbacks should not wait for each other.
No, you aren't right.
Socket I/O proceeds independently for each socket.
I know that in order to call WSASend() simultaneously, I need to provide for each call a unique WSAOVERLAPPED and WSABUF instances. But this means that I have to keep track of these instances for each call, which will complicate things.
I think it would be a better idea if I create a thread that only make WSASend() calls not simultaneously but rather sequentially. This thread will wait on a queue that will hold WSASend() requests (each request will contain the socket handle and the string I want to send). When I eventually call WSASend() I will block the thread until I receive a wake up signal from the thread that waits on the completion port telling me that the WSASend() has been completed, and then I go on to fetch the next request.
If this is a good idea, then how should I implement the queue and how to make a blocking fetch call on it (instead of using polling)?
The WSABUF can be stack based as it is the responsibility of WSASend() to duplicate it before returning. The OVERLAPPED and the data buffer itself must live until the IOCP completion for the operation is extracted and processed.
I've always used an 'extended' OVERLAPPED structure which incorporates the data buffer, the overlapped structure AND the WSABUF. I then use a reference counting system to ensure that the 'per operation data' exists until nobody needs it any more (that is I take a reference before the API call initiates the operation and I release a reference when the operation is completed after removal of the completion from the IOCP - note that references aren't 100% necessary here but they make it easier to then pass the resulting data buffer off to other parts of the code).
It is MOST optimal for a TCP connection to have the TCP "window size" of data in transit at any one time and to have some more data pending so that the window is always kept full and you are always sending at the maximum that the connection can take. To achieve this with overlapped I/O it's usually best to have many WSASend() calls pending. However, you don't want to have too many pending (see here) and the easiest way to achieve this is to track the number of bytes that you have pending, queue bytes for later transmission and send from your transmission queue when existing sends complete...
I have read that you are not supposed to use send() on a blocking socket from multiple threads, but I do not know why! And if I want to use send() from multiple threads, is there anything I can do to allow it?
I am using Windows.
The fundamental reason is that synchronous I/O functions use the handle object (sockets are implemented as handles) to keep track of whether the I/O is complete or not.
The result is that if you try to send() to the same socket from multiple threads simultaneously, send() is liable to (a) hang or (b) exit before the I/O is actually complete, with catastrophic results.
You can use a critical section to prevent the sends from overlapping, or have a designated thread that reads data to send from a queue.
Note that this only applies if the sends are to the same socket. Sending to different sockets simultaneously is fine.
What is the best way to read and write from multiple client sockets on a single thread? I've heard that select() is oldschool and there are better options available. Is the best option currently to use one of WSAAsyncSelect, WSAEventSelect?
Also, what is the difference between WSARecv() and recv(), and WSASend() and send()? Are the WSA versions the most modern way to send and recv data through winsock?
If your single thread is also implementing a GUI then WSAAsyncSelect is designed for this purpose: You get your socket notifications through messages in the Windows queue that your GUI thread must service anyway.
If your single thread is dedicated to the sockets and does not need a message loop, then WSAEventSelect might be more convenient, and a little faster.
At my multithread application I using AF_UNIX type of socket. Seems by default its blocking. The question is whats mean by "blocking"? Is it block the thread when it execute the ::recv or ::send calls or all threads on the application (like fgets do)?
If it block all threads/whole application, I guess need to use non-blocking sockets? If so, please, give the good example of how to set up AF_UNIX non-blocking socket and when need to set non-blocking mode (and how). How to ::recv ? thanks.
Blocking calls make the thread wait for the operation to complete. Use them when your thread cannot continue before the operation has completed, for example due to the data dependency on the input being received.
Non-blocking calls return as soon as the information is buffered for transmission, or the read operation is initiated. Use them when there are no data dependencies.
In general, blocking always means "blocks the current thread", not "block all threads in my process.
It only blocks the thread that makes the recv call.