network delays and Application->ProcessMessages()
I am writing a networking DLL that I use in my C++Builder project. This DLL works with remote FTP servers. I noticed a strange behavior when recv()
is called. Sometimes it returns 0. But in another thread when recv()
is called on the same socket, data is received as expected.
What does this mean? I also noticed t开发者_运维百科hat calling Application->ProcessMessage()
inside the DLL thread speeds up data receiving.
But what is wrong? Doesn't ProcessMessages()
just process window messages or am I missing something?
Thank you
If I understood you correctly and you are trying to recv
on the same SOCKET
in parallel threads then don't do that, there is nothing to gain from it. The data you are recv
is already buffered by the underlying system and you are accessing that, the thing you could do is to make multiple buffers for the recv
so that when it returns data you could pass one buffer to the "upper levels" for processing and use the other one for the new recv
call. You can also use just one large buffer with notifications what is for processing and what part is being used for receiving. The system probably has locks that forbid multiple reading on the same socket and so the result in one recv
is 0
. If it didn't have that you would probably end up with some almost randomly split data.
EDIT: Full and long explanation
I think that using multiple threads to read from a single socket is not useful
Sockets are a software regulated thing. You network device doesn't create any "connections", it just processes the data received and wraps/unwrapps them into IP
(or any other
supported Internet Layer) packets (the previous depending on the network device, some of them are almost entirely software emulated by the os and actually perform just the basic "write to tx-read rx" services but to us its the same deal) . The WinSock2
service recognizes packets with specific data ( as you have already noticed ) so that you may use one network device for simultaneously
communicating with multiple peers. WinSock2
activly monitors the traffic before handing it out to you. In other words: when you are about to get a successfull recv
the data
was already there and the underlying system has checked the socket you used as a parameter in recv
and only handed you over the data that has already been marked as the data
for that socket. Reading with multiple threads from one socket (without the almost useless MSG_PEEK
) would make the system, if it didn't have locks, copy unknown number of bytes
to the location supplied in recv
in the thread one and increment the internal pointer to data by number of copied bytes permanently, then, before whole data availible in the
recv
is copied at the location1, the other thread would kick in and copy also unknown number of bytes thus also incrementing the internal pointer to data by that many bytes.
Result of this type of reading would ideally be half of the data stored from location supplied in thread 1, the other half starting from location supplied in thread 2. Since the ideal result is uncertain (time allocated by the system for theese two threads is not guarantied to be equal) you would end up with unsorted data without any means of sorting
it, since the info that the underlying system uses for knowing what data belongs to which socket will not be able to you.
Being that your system is most likely faster than your network device I stand by my two solutions, first one prefered as I have been using this method for both big and small chunks of data transfer:
Make one reading thread per connected socket and one circular buffer, size of the buffer depends on the size of chunks you expect to receive and the time you will need to process the stuff further, save current read position, save "to process count", when data is received notify the thread/threads that it is supposed to process the data in the buffer, save the position of the data being used for reading, continue
recv
if there is buffer space not being processed else wait until there is (must implement this in case your computer chokes somewhere, in normal situations it shouldn't). You must sync the receiving thread with the processing thread/threads when they are accesing the "to_process_count" and "current read pos" vars as those will tell you which bytes you can reuse in your circular buffer.Create and connect one socket per desired reading thread so that the system will know how to regulate the data on its own
The thing you are refering too as random threads reading from a single socket, is maybe acievable through the following scenarios:
1 Thread Enumerates socket to see if there is data availible when data is availible it uses some mutex to wait if some thread is already in the reading state starts a new thread to read and process the existing data
or it can be achieved with something like this
Thread does its recv
as soon as it has done a successful recv
(yey, the data is in the buffer) it starts another thread from some thread pool to do recv
and continues to process data and end itself
Theese are the only ways I can imagine that "reading with multiple threads on a single socket" is achievable. Yes, there won't be multiple threads calling recv
at the same time
Sorry for the long post, the spelling and grammar errors and hope this helps you a bit
Ensure that socket is properly bound to the handle you are using in recv
function.
You cannot speedup data reception, unless there is channel to receive the data.
精彩评论