Hi I'm working on a networking project. I've a socket that is listening incoming data. Now I want to archive this: Socket will receive only 100 packets. And there is 3-4 clients. They are sending random data packets infinitely. I'll receive 100 packets and later I'll process them. After process I'll re-start receiving. But at this time there are some pending send() >> recv() operations. Now I want to cancel/discard pending recv operations. I think we'll recv datas and we'll not process them. Any other suggestions? (sorry for bad question composition)
Shutdown and close the connection. That will cancel everything immediately.
Better yet, rearchitect your application and network protocol so that you can reliably tell how much data to receive.
On Windows you can cancel outstanding receives using CancelIO, but that might result in lost data if the receive just happened to read something.
You can use select() or poll() loops.
you can use signal. recv() will return on receiving a signal so you can send a signal from another task to the task that blocks on recv(). But you need to make sure you don't specify SA_RESTART (see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html)
Read http://en.wikipedia.org/wiki/Asynchronous_I/O for more details
I would go with non-blocking sockets + cancellation socket.
You'll have to read into dedicated incremental buffer (as recv() may not receive all the data expected at once - this would be the case if you can only process full messages) and return to select()/poll() in your loop, where you can safely sit and wait for:
next data
next connection
cancellation event from a cancellation socket, to which your other thread will send a cancellation signal (some trivial send()).
UPD: the trivial event may be the number of the socket in the array or its handle - something to identify which one you'd like to cancel.
Related
I'm trying to create a server with blocking sockets (one new thread for each new client). This thread should be able to receive commands from the client (and send back the result) and periodically send commands to the client (and request back the result).
What I've thought is creating two threads for each client, one for recv, second for send. However:
it's double of the normal thread overhead.
due to request/response design, recv I do in the first thread (to wait for client's commands) can be the request I look for in the second thread (client's result to my send) and vice versa. Making it all properly synced is probably a hell story. So now I'm thinking to do that from a single thread this way:
In a loop:
setsockopt(SO_RCVTIMEO, &small_timeout); // set the timeout for the recv (like 1000 ms).
recv(); // check for client's requests first. if returns WSAETIMEDOUT than I assume no data is requested and do nothing. if I get a normal request I handle it.
if (clientbufferToSend != nullptr) send(clientbufferToSend); // now when client's request has been processed we check the command list we have to send to the client. if there is commands in queue, we send them. SO_SNDTIMEO timeout can be set to a large value so we don't deadlock if client looses connection.
setsockopt(SO_RCVTIMEO, &large_timeout); // set the timeout for the recv (as large as SO_SNDTIMEO, just to not deadlock if anything).
recv(); // now we wait the response from the client.
Is this the legal way to do what I want? Or are there better alternatives (preferrably with blocking sockets and threads)?
P.S. Does recv() with timeout returns WSAETIMEDOUT only if no data is available? Can it return this error if there is the data, but recv() wasn't fast enough to handle it all, thus returning partial data?
One approach is only create a background thread for reading from that socket. Write on whatever random thread your unsolicited events are raised.
You’ll need following stuff.
A critical section or mutex per socket to serialize writes, like when background thread is sending response to client-initiated message, and other thread wants to send message to the same client.
Some other synchronization primitive like a conditional variable for client thread to sleep while waiting for responses.
The background thread which receives messages needs to distinguish client-initiated messages (which need to be responded by the same background thread) from responses to server-initiated messages. If your network protocol doesn’t have that data you’ll have to change the protocol.
This will work OK if your server-initiated events are only happening on a single thread, e.g. they come from some serialized source like a device or OS interface.
If however the event source is multithreaded as well, and you want good performance, you gonna need non-trivial complexity to dispatch the responses to the correct server thread, like 1 conditional variable per client thread, maybe some queues, etc.
I have an applications with 2 threads. The first thread (main-thread) and the second thread (tcp-client-thread). The main-thread generates some messages and puts their in queue for tcp-client-thread. tcp-client-thread has to send those messages to server. But, tcp-client-thread also has to receive some messages from server.
How can I do that? recv stops current thread. Set up timeout forrecv? Then after recv timeout check queue (from main-thread) and if there is messages send their is no any messages start recv again?
You can do your I/O in one non-spinning/non-delayed thread but it's much more complex then just simply creating another thread as suggested in another answer. In short, you'll have to modify your code to handle waiting for multiple event types simultaneously, i.e. an event on the socket OR on a condition signalling data to send, for example. On Windows, you'd use something like WSAEventSelect + WaitForMultipleObjects instead of select, and on Linux you'd use something like eventfd with select. Note that when handling the socket, if it's blocking, you'd want to check for readability before issuing a recv and check for writeability before issuing a send so you don't block on one or the other. Like I said though, easier to just create a send thread...
The thing you need is non-blocking/asynchronous I/O.
You should read some theory before trying to forge any code.
This article, for example:
http://www.wangafu.net/~nickm/libevent-book/01_intro.html
If you are going to use 2 threads, you might want to extend to 3 threads. Let the send and receive functions be on separate threads.
The send thread is sleeping until the main thread gives it data. Specifically, a function in the send software unit places data into the queue, then signals the thread to wake up. The thread wakes up and sends data until the queue is empty, then it goes back to sleep.
Conversely, the receive thread sleeps until it receives data. It appends data to another queue, notifies the main thread that data was received and goes back to sleep.
Edit 1: One Thread
Per your title, if you want to perform the I/O in one thread, you will need to have a polling loop (you can have limited waiting, but not advised).
Loop:
if (data received) then place data into input queue.
if (data in input queue) process some data (use small chunks).
if (data in output queue) send some data.
end-loop.
The idea is to keep the blocks of data small to prevent missing of incoming data. The data can be processed and output when there is no data (and with multiple iterations). This will resolve most synchronization issues.
using socket with the overlapped operation selected the event-based completion notification;
Have 2 events, one for data, the other to cancel long send/recv:
HANDLE events[] = { m_hDataEvent, m_hInterruptEvent };
then calling WSASend,
WSASend(m_Socket, &DataBuf, 1, NULL, 0, &SendOverlapped, NULL);
followed by
WSAWaitForMultipleEvents(2, events, FALSE, INFINITE, FALSE);
which is setup to return on any one event signaled.
Now assume send is in progress, and m_hInterruptEvent is signaled.
WSAWaitForMultipleEvents returns, technically the function calling send can return as well and delete internally allocated buffers.
What is not clear to me, the WSASend may still be working in background, and deleting buffers will cause data corruption in best case.
What would be the proper way to stop the background Send/Receive, if the socket needs to be used for something else immediately?
I looked at the CancelIO(), but the MSDN never mentions it in relation to Sockets, does it work with file based IO only?
It makes no sense to try to cancel it once sent. Even if you succeeded you would have a problem because the receiving application would not have any idea that the transmission was interrupted. Your new message will be mistaken for the end of the old message.
If you feel the need to cancel long sends, you should probably look at your application design.
Send in chunks and check for cancellation in between chunks. Ensure you have a way of communicating to the receiver that the transmission was cancelled.
Close the socket to cancel. Again, ensure the client has a way to know that this is an interrupted transmission (for example if the client knows the total length in advance they will recognise an interrupted transmission).
Just wait for it to succeed in the background and don't worry. If you have urgent messages use a separate connection for them.
For your particular question "What would be the proper way to stop the background Send/Receive, if the socket needs to be used for something else immediately", the answer is: Sockets are cheap - Just use two - one for the slow transmission the other for the urgent messages.
how to send and receive data and acknowledgement asynchrounously in c++ socket tcp/ip?, i can see in my program as when send some 145 byte data 50 times , i will be receiving the acknowledgement for the first six as it takes time to give the acknowledgement. I have tried waiting until i receive the acknowledgement for the current sent data, but it takes long time , which i dont want to do. I want to process with the data. So what i thought is i will put receive in a separate thread. and i want to process receive simultaneouly while send is happening? So Asynchronous receive will work? Can anyone help? The class which i am using to receive and send data is a static class. As i needed to call from two other classes to send data to same ip and port.
You can use socket for sending data in one thread and for receiving data in another thread, simultaneously. The thing you cannot do is performing the same action (sending or receiving) on the same socket from different threads.
Nevertheless, always try to avoid adding new threads if unnecessary. You can use some socket functions (select, WSAEventSelect) that will notify you when you can perform read/write on the socket. Put them in a loop in a single thread, wait for events and handle them - read/write in the same thread. If you need to process received data and that takes time, store received data in a queue shared with another, data processing thread. Of course, bear in mind you would need to make this queue thread-safe and synchronise socket and data processing thread.
If on Posix systems, you might need a multiplexing system call like poll or ppoll or pselect or select
If your system is non-Posix (e.g. windows) you should find some similar functionality, or use threads.
In my program there is one thread (receiving thread) that is responsible for receiving requests from a TCP socket and there are many threads (worker threads) that are responsible for processing the received requests. Once a request is processed I need to send an answer over TCP.
And here is a question. I would like to send TCP data in the same thread that I use for receiving data. This thread after receiving data usually waits for new data in select(). So once a worker thread finished processing a request and put an answer in the output queue it has to signal the receiving thread that there are data to send. The problem is that I don't know how to cancel waiting in select() in order to get out of waiting and to call send() .
Or shall I use another thread solely for sending data over TCP?
Updated
MSalters, Artyom thank you for you answers!
MSalters, having read your answer I found this site: Winsock 2 I/O Methods and read about WSAWaitForMultipleEvents(). My program in fact must work both on HP-UX and Windows I finally decided to use the approach that had been suggested by Artyom.
You need to use something similar to safe-pipe trick, but in your case you need to use a pair of connected TCP sockets.
Create a pair of sockets.
Add one to the select and wait on it as well
Notify by writing to other socket from other threads.
Select is immediately waken-up as one of the sockets is readable, reads all the
data in this special socket and check all data in queues to send/recv
How to create pair of sockets under Windows?
inline void pair(SOCKET fds[2])
{
struct sockaddr_in inaddr;
struct sockaddr addr;
SOCKET lst=::socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);
memset(&inaddr, 0, sizeof(inaddr));
memset(&addr, 0, sizeof(addr));
inaddr.sin_family = AF_INET;
inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
inaddr.sin_port = 0;
int yes=1;
setsockopt(lst,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes));
bind(lst,(struct sockaddr *)&inaddr,sizeof(inaddr));
listen(lst,1);
int len=sizeof(inaddr);
getsockname(lst, &addr,&len);
fds[0]=::socket(AF_INET, SOCK_STREAM,0);
connect(fds[0],&addr,len);
fds[1]=accept(lst,0,0);
closesocket(lst);
}
Of course some checks should be added for return values.
select is not the native API for Windows. The native way is WSAWaitForMultipleEvents. If you use this to create an alertable wait, you can use QueueUserAPC to instruct the waiting thread to send data. (This might also mean you don't have to implement your own output queue)
See also this post:
How to signal select() to return immediately?
For unix, use an anonymous pipe. For Windows:
Unblocking can be achieved by adding a dummy (unbound) datagram socket to fd_set and then closing it. To make this thread safe, use QueueUserAPC:
The only way I found to make this multi-threadsafe is to close and recreate the socket in the same thread as the select statement is running. Of course this is difficult if the thread is blocking on the select. And then comes in the windows call QueueUserAPC. When windows is blocking in the select statement, the thread can handle Asynchronous Procedure Calls. You can schedule this from a different thread using QueueUserAPC. Windows interrupts the select, executes your function in the same thread, and continues with the select statement. You can now in your APC method close the socket and recreate it. Guaranteed thread safe and you will never loose a signal.
The typical model is for the worker to handle its own writing. Is there a reason why you want to send all the output-IO through selecting thread?
If you're sure of this model, you could have your workers send data back to the master thread using file descriptors as well (pipe(2)) and simply add those descriptors to your select() call.
And, if you're especially sure that you're not going to use pipes to send data back to your master process, the select call allows you to specify a timeout. You can busy-wait while checking your worker threads, and periodically call select to figure out which TCP sockets to read from.
Another quick&dirty solution is to add localhost sockets to the set. Now use those sockets as the inter-thread communication queues. Each worker thread simply sends something to its socket, which ends up on the corresponding socket in your receiving thread. This wakes up the select(), and your receiving thread can then echo the message on the appropriate outgoing socket.