I find that in many cases, even though WSASend succeeds
and reports all of the bytes sent, the message never makes
it to the wire, as confirmed by an Ethernet sniffer.
It seems that sharing the socket among several clients is
the likely cause of this. I tried serializing access to
the socket with a critical section, but this does not fix
this problem.
I have tried both blocking and overlapped calls and this
makes no difference.
Anyone have experience with this? Thanks in advance for
any light you can provide on this.
Thanks,
Bob Gaffaney
Siemens SBT
If you post another send() on the same connection while a
first send() is still in the works, winsock may chose to
append some or all of the data from the second operation.
e.g. If two threads each send 1000 bytes, the application
on the far end may recv() two packets of 1000 bytes; one
packet of 2000 bytes or even one of 1440 bytes and one of
560 bytes.
Logically, what I am sending are datagrams - though end to
end delivery integrity is required so we are using TCP not
UDP.
If there is a way to make Winsock to send the messages as
sent that would be preferable, else I will have to send
them in a single thread and provide enough information to
disassemble them on the far end.
Any suggestions?
Thanks
Bob Gaffaney
>.
>
Arkady
"Bob Gaffaney" <bob.gaf...@sbt.siemens.com> wrote in message
news:1695d01c227bc$e032b670$9ae62ecf@tkmsftngxa02...
Bob,
TCP is a byte stream. The developer always has to do the work required to
break the byte stream into protocol specific chunks. From what you describe,
the easiest way to do this would be to include a header in your 'datagram'
and have that header contain the length of the packet. Then you read the
header, work out how many more bytes make up one packet and process that
packet.
We have some articles on our website which cover this kind of thing:
http://www.jetbyte.com/portfolio-showarticle.asp?articleId=37&catId=1&subcat
Id=2
--
Len Holgate
http://www.jetbyte.com
The right code, right now.
Contract Programming and Consulting Services.
This is TCP's choice, not Winsock's. All TCP stacks do this.
>Logically, what I am sending are datagrams - though end to
>end delivery integrity is required so we are using TCP not
>UDP.
>
>If there is a way to make Winsock to send the messages as
>sent that would be preferable, else I will have to send
>them in a single thread and provide enough information to
>disassemble them on the far end.
That's exactly what you'll have to do. Fine, you've decided that TCP's
reliability is needed, so you use TCP; but TCP doesn't care about your
datagrams, and does nothing to indicate where they start or end - you'll have
to do that. You'll have to insert bytes into the stream that your application
can use to determine where the "datagrams" begin and end, and you'll have to
ensure that you've read every byte of each one before you process it.
The most common methods to use are delimiter characters (or character
sequences), with quoting to allow the delimiter to appear in the message
itself, or length counts.
Alun.
~~~~
[Please don't email posters, if a Usenet response is appropriate.]
--
Texas Imperial Software | Try WFTPD, the Windows FTP Server. Find us at
1602 Harvest Moon Place | http://www.wftpd.com or email al...@texis.com
Cedar Park TX 78613-1419 | VISA/MC accepted. NT-based sites, be sure to
Fax/Voice +1(512)258-9858 | read details of WFTPD Pro for NT.
This would involve adding a fixed-size header (more then just a "delimiter")
to each "message" that is sent by any thread. The fixed header would
identify the contents of each message and possibly have a sequence number,
etc. Most importantly, the fixed header would include a length field that
identifies the length of data in your "message". The receiver would always
read for the fixed header. Once found, examine header. From header length
field, make as many reads as necessary to read the length and then go
process that.
Your receive will have to buffer received data and glue it together based on
header information. Then pass received "message" for processing.
May sound like a little more work then you want to do. However, if you do it
systematically it has many virtues.
Good luck,
--
Thomas F. Divine
PCAUSA - Tools & Resources For Network Software Developers
NDIS Protocol/Intermediate/Hooking - TDI Client/Filter
<http://www.pcausa.com> - <http://www.rawether.net>
"Alun Jones" <al...@texis.com> wrote in message
news:dqWW8.200$p72.17...@newssvr11.news.prodigy.com...
WSASend 1: buffer = a b c d
WSASend 2: buffer = 1 2 3 4
Received: a b 1 2 3 c d 4
?
OR are you saying there's no guarantee in which order the blobs "1234" and
"abcd" will be received?
JD
"arkadyf" <ark...@hotmail.com> wrote in message
news:uOKTMX9JCHA.1608@tkmsftngp09...
[snip]
Thanks,
Bob
>.
>
JD
"Bob Gaffaney" <bob.gaf...@sbt.siemens.com> wrote in message
news:149e401c22841$a0f48580$a5e62ecf@tkmsftngxa07...
Arkady
"John Duddy" <jdu...@idontwantyourunsolicitedmsgDOTstbernard.com> wrote in
message news:uip544c...@corp.supernews.com...
So, have you seen this intermingling occur? I'd hate to impose unnecessary
serialization on a high-performance app unless it is necessary, and then
only as much as is needed to ensure safe, predictable operation.
Thanks -
JD
"arkadyf" <ark...@hotmail.com> wrote in message
news:eA5JbbLKCHA.2320@tkmsftngp11...
Once data is honored to be sent, the stack will guarantee the order of the
stream as accepted; otherwise you would see data corruption.
On the other hand, some kind of synchronization has to be in place. For
example, if you request "abcd" to be sent, it is possible only part of the
request will be honored and only "ab" will be sent, If the other send
request of "1234" is fully honored, the receiving end will see "ab1234".
Thus, it is critical to verify how many bytes are actually sent for each
operation and implement the synchronization mechanism accordingly.
Thanks,
Mike Liu
Microsoft Developer Support
This posting is provided "AS IS" with no warranties, and confers no rights.
JD
"Mike Liu (MS)" <mike...@online.microsoft.com> wrote in message
news:Na2X10fKCHA.2328@cpmsftngxa08...
"John Duddy" <jdu...@idontwantyourunsolicitedmsgDOTstbernard.com> wrote in
message news:uiuvc5i...@corp.supernews.com...
It's worth noting that a common - and effective - solution to this is to have
each socket only writable by one thread. That way, you can not ever
intermingle two sets of data. A mutex on the socket or its buffer is
generally a lot of trouble, and can lead to messy code - besides, the socket
is a serial device, and therefore isn't going to benefit from parallelisation,
until and unless the following becomes true:
1. You're running on multiple processors.
2. Your immediate processing on network input takes longer than the traffic
takes to come in.
For many - perhaps even most - applications, the second part is false.
The only time multiple threads can come into play in this scenario is when
you are using an IOCP with multiple threads servicing it. If sequntially
issued overlapped WSASend operations do not complete sequentially and in
their entirety (i.e. partial completion requiring re-issuing the WSASend for
the unsent portion of the buffer) then IOCP is essentially crippled in
winsock applications. I can see no other conclusion.
All of this was started by someone saying the buffers get intermingled. If
that is so, then you can never safely use IOCP with winsock. Can anyone else
see another conclusion, or should we re-examine the assertion that the
buffers sent via two overlapped WSASend operations can be intermingled?
Thanks for your patience for my pedanticism ;-}
JD
writes.
"Alun Jones" <al...@texis.com> wrote in message
news:s6hY8.5751$jJ2.2028823720@newssvr12.news.prodigy.com...
We've been doing a lot of work in this area recently. We have a TCP/UDP test
harness that we have been testing our IOCP servers with and it exposed a
problem with multiple WSASend() operations being executed out of sequence.
However, this was merely because our design uses the IOCP to "marshal" the
socket IO calls into the IO thread pool rather than executing the sends in
user threads that may, potentially, be terminated before the IO completes.
Because we're testing on a multi-processor box and because we have multiple
IO threads servicing our IOCP the WSASend() requests were suffering from the
problem more usually associated with multiple WSARecv()s and our test
harness flushed that out. The problem was that the actual calls to WSASend()
were being processed out of sequence. After putting in some code to ensure
that the buffers for each send had a sequence number in them that was
incremented by each write operation, and some code in the IOCP worker thread
to ensure that the send operations were actually executed in the required
sequence our problems went away.
I have never seen an overlapped WSASend() complete and report a partial
buffer transmission. I cannot believe that this could occur except in the
case where the connection is closed mid send and even then I've never seen
it. As you point out, if the WSASend() could complete and indicate that it
had only sent part of the buffer then the whole IOCP model would be fatally
flawed because there's no way of knowing how many other send's are queued
up, so there's no way of ever being able to recover and send the rest of the
partially transmitted buffed in the correct place in the byte stream.
I have never seen buffers intermingled in the way that is suggested by the
other poster either. As you say, that would also make the IOCP model
unworkable.
My tests have made me confident that these problems with the API just do not
exist. There are plenty of programmer induced problems that could cause
similar behavior, but they're just bugs ;)
In case you're interested, we have an article on our web site about the how
to have multiple outstanding WSARecv() and WSASend() operations operate as
expected in a multi threaded, multi processor, IOCP design.
http://www.jetbyte.com/portfolio-showarticle.asp?articleId=44&catId=1&subcat
Id=2
And another article about our C# server test tool. This tool provides a
framework that you can plug protocol specific tests into, and makes sure
that the server can deal with message fragmentation, partial and multiple
messages, etc.
http://www.jetbyte.com/portfolio-showarticle.asp?articleId=46&catId=4&subcat
Id=11
Each article comes with complete source code.
JD
"Len Holgate" <Len.H...@JetByte.com> wrote in message
news:3d3311cd$0$8509$cc9e...@news.dial.pipex.com...
Arkady
"John Duddy" <jdu...@idontwantyourunsolicitedmsgDOTstbernard.com> wrote in
message news:uj66hnt...@corp.supernews.com...
Would this occur at the point where you make the WSASend call, rather than
via the completion port? If it occurs at that point you could, maybe, still
be able to do someting about it. Either way, if you're out of non paged pool
you're probably screwed anyway...
Arkady
"Len Holgate" <Len.H...@JetByte.com> wrote in message
news:3d36d3e2$0$238$cc9e...@news.dial.pipex.com...