Sockets

D

Dmitry Akselrod

Sockets Programming Question:



I have two applications. One is a server, one is a client. However, both
listen on certain ports for communication. The server is written in vb.net
(framework v.1.0) and the client is written in vb6 sp5 because vb6 uses far
less resources.



One of the routines in the programming involves the server sending a rather
large xml string to the client:



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



Public Sub sendMessage(ByVal MessageText As String)



Try

If bIsConnected Then

If networkStream.CanWrite Then

Dim sendBytes As [Byte]() =
Encoding.ASCII.GetBytes(MessageText)

networkStream.Write(sendBytes, 0, sendBytes.Length)

End If

End If

Catch e As System.Net.Sockets.SocketException

Debug.WriteLine("Connection" & vbCrLf & e.Message)

appLog.WriteEntry("Connection Error" & vbCrLf & e.Message,
EventLogEntryType.Error, 1022)

End Try



Debug.WriteLine("CLIENT>Sending message to: " & sMachineNetBIOSName)

Debug.WriteLine("CLIENT>: " & MessageText)

End Sub





~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



The client receives the message and writes it to a string, then sends it for
processing:



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



Private Sub axWinsockServer_DataArrival(ByVal bytesTotal As Long)

Dim strData As String 'where the data sent by the client will be stored

Call axWinsockServer.GetData(strData, vbString) 'gets the data sent by
the client



Call WSS_ProcessData(strData)

End Sub



Private Sub WSS_ProcessData(ByVal sData As String)



Dim JobCodeRequest As New JobCodeClass



Set JobCodeRequest = ProcessXML.ProcessXML(sData)



If JobCodeRequest.JobID <> 0 Then JobCodeRequestCollection.Add
Item:=JobCodeRequest



Call DisplayPopUp(JobCodeRequest)



axWinsockServer.Close

If (axWinsockServer.State <> sckListening) Then axWinsockServer.Listen



Debug.Print ("Data Received: " & sData)



End Sub



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



The function ProcessXML.ProcessXML just processes the xml in the string.



The problem is as follows:



When I run a network monitor to capture the traffic caused by transfer of
this large xml string, I notice that the string is split up in several
packets of 1460 bytes maximum in length. When the client is installed on
some workstations, the client receives the string as a single xml string.
One other workstation, the client receives several strings of 1460 bytes
maximum, thus truncating the xml string and invalidating it in the process.
Since the problem occurs on some workstations, I am guessing the problem is
either network card specific or there is a setting in the registry that
controls the maximum length a socket can send and receive. I am guessing
that Ethernet is optimized to a certain packet length. (BTW, all machines
are XP or Windows 2000, NICs vary).



Should I rewrite my code to analyze the networkstream size and break it down
manually to a max of, let’s say 1000 bytes long? I would have to implement
some kind of continuation method to insure that the strings received on the
client side are concatenated together. Or should I adjust the default send
and receive packet length?



I am guessing I should adjust my code. Has anyone seen this before? Does
anyone have any advice or a good method to implement continuation of
packets?



I suppose that alternately I can ftp the xml file to the client or setup a
web server as part of my code and retrieve the file via simple http get. I
would rather not add this extra code to my software however.



Thank you very much,



Dmitry Akselrod
 
J

Jeff Johnson [MVP: VB]

Please do not crosspost questions between .NET and non-.NET groups. The
*.vb.* groups are for VB6 and earlier. The *.dotnet.* groups are
for--surprise!--.NET.
 
A

Andrew Faust

Dmitry Akselrod said:
Sockets Programming Question:



The server is written in vb.net
(framework v.1.0) and the client is written in vb6

Doesn't matter. The Server can be a Mac and the Client can be my
XBox. That's the beauty of standardized network protocols.

The problem is as follows:



When I run a network monitor to capture the traffic caused by transfer of
this large xml string, I notice that the string is split up in several
packets of 1460 bytes maximum in length. When the client is installed on
some workstations, the client receives the string as a single xml string.
One other workstation, the client receives several strings of 1460 bytes
maximum, thus truncating the xml string and invalidating it in the process.

The problem is because when you send data it is actually chopped up
and sent as packets, and then reconstructed at the destination. In the
case of VB6 with the winsock control, you may need to keep grabbing
chunks of data and concatenating it together to get the full packet.

The way I handle this is to first send a message telling how large
the data will be. I then keep reading from the socket stream until
I've read that many bytes.
Since the problem occurs on some workstations, I am guessing the problem is
either network card specific or there is a setting in the registry that
controls the maximum length a socket can send and receive.

No. Most likely the reason it happens sometimes is due to the network
bandwidth. The first time I hit this problem was when I was testing an
app where the client and server were on the same machine and it worked
great, but as soon as I used the server on a different machine this issue
arose.
I would have to implement
some kind of continuation method to insure that the strings received on the
client side are concatenated together.

Bingo.
 
T

Tom Shelton

Sockets Programming Question:



I have two applications. One is a server, one is a client. However, both
listen on certain ports for communication. The server is written in vb.net
(framework v.1.0) and the client is written in vb6 sp5 because vb6 uses far
less resources.

I am guessing I should adjust my code. Has anyone seen this before? Does
anyone have any advice or a good method to implement continuation of
packets?



I suppose that alternately I can ftp the xml file to the client or setup a
web server as part of my code and retrieve the file via simple http get. I
would rather not add this extra code to my software however.



Thank you very much,



Dmitry Akselrod

Dmitry

What your experiencing is the normal behavior of TCP. TCP is a
streaming protocol. Data is broken into chunks and then reassembaled on
the other end.

Generally when sending data back and forth across tcp socket you need to
have some sort of end of stream marker - which for text is commonly a
CR+LF combo - or know exactly how many bytes you are to recieve.

So, assuming a text stream with CR+LF as a terminator, the recieve would
do something like:

1. receive data
2. append to buffer
3. did I recieve my terminator?
a. Yes - Exit
b. No - goto 1

HTH
 
D

Dmitry Akselrod

Andrew Faust said:
process.

The problem is because when you send data it is actually chopped up
and sent as packets, and then reconstructed at the destination. In the
case of VB6 with the winsock control, you may need to keep grabbing
chunks of data and concatenating it together to get the full packet.

The way I handle this is to first send a message telling how large
the data will be. I then keep reading from the socket stream until
I've read that many bytes.

Excellent! That's what I was looking for, thank you for the advice!

No. Most likely the reason it happens sometimes is due to the network
bandwidth. The first time I hit this problem was when I was testing an
app where the client and server were on the same machine and it worked
great, but as soon as I used the server on a different machine this issue
arose.

I think that you have a point there. After further analysis, I determined
that the workstations that are physically further away from the server
applications are the ones having most of the trouble.

Thanx again,

Dmitry
 
D

Dmitry Akselrod

Tom Shelton said:
Dmitry

What your experiencing is the normal behavior of TCP. TCP is a
streaming protocol. Data is broken into chunks and then reassembaled on
the other end.

Generally when sending data back and forth across tcp socket you need to
have some sort of end of stream marker - which for text is commonly a
CR+LF combo - or know exactly how many bytes you are to recieve.

So, assuming a text stream with CR+LF as a terminator, the recieve would
do something like:

1. receive data
2. append to buffer
3. did I recieve my terminator?
a. Yes - Exit
b. No - goto 1

Tom, thanx. I will look for for CR and LF characters.
 
T

Tom Shelton

Tom, thanx. I will look for for CR and LF characters.

Dmitry,

Only do that if that is how your string is terminated... I was just
pointing out that CR+LF is the common choice, but it can just as easily
(and I've seen it done) be a null byte. This isn't something that is
defined by the TCP layer, but by the protocol that you develope on top
of TCP.

HTH
 
N

NickD

Dmitry Akselrod said:
Sockets Programming Question:
[...]
One of the routines in the programming involves the server sending a rather
large xml string to the client: [...]

The problem is as follows:



When I run a network monitor to capture the traffic caused by transfer of
this large xml string, I notice that the string is split up in several
packets of 1460 bytes maximum in length. When the client is installed on
some workstations, the client receives the string as a single xml string.
One other workstation, the client receives several strings of 1460 bytes
maximum, thus truncating the xml string and invalidating it in the process.
Since the problem occurs on some workstations, I am guessing the problem is
either network card specific or there is a setting in the registry that
controls the maximum length a socket can send and receive. I am guessing
that Ethernet is optimized to a certain packet length. (BTW, all machines
are XP or Windows 2000, NICs vary).
[...]

It's quite normal to expect TCP/IP at this level of the protocol stack to
chop up your data into packets of various sizes and spit them down the wire.
This is why most (estabilished) TCP internet protocols you see base their
"send complete" or packet terminators as unique values at the end.. for
example, let's take POP3.

When you request an email from a POP3 server you issue the command: RETR
<msg number> <CRLF>

The server doesn't give a fig for what the packet sizes are, nor does it
use/assume fixed lengths for the commands you send it. It simply waits for
the <CRLF> and then parses the info leading up to it.

Assuming you requested a valid email, the reply may be much larger and over
many lines. Clearly, terminating on <CRLF> is a no-no. So instead it
terminates on <CRLF>.<CRLF>, and it guarantees (by munging the email*) that
the only place this particular byte sequence will occur is to signal that it
has finished sending the email to the client, which could have been
streaming MBs of data in thousands of packets until that point.

Because POP3 is over a TCP stream, other IP issues such as packet integrity
and sequencing are handled for you (not so with UDP, you're on your own), so
really only controlling the "language" of the protocol is of concern. Using
a method such as that described above, or one like that used by HTTP POST
where it indicates in a "header" at the beginning of the transmission how
big the following chunk of data is going to be, are amongst the most common
ones for handling varying length communications.

Either way you will not be able to force/guarantee the packet size and will
need to keep concatenating the data you receive in chunks at the other end
until you've reached your limit/marker to signal the end.

Trying to work against the TCP/IP configuration and trying to force the MTU
and other properties to manage your data in a single chunk is actually just
more likely to degrade network performance (not just for your app, but for
all other network communications over the same wire) and/or cause network
failures. These days, the self-tuned values in use by the devices and
drivers that deal with network protocols are best left alone.

Regards,
Nick

* If it detects a <CRLF>.<CRLF> sequence in the email anywhere, to prevent
premature termination by the receiving app I believe it just adds a space
after the period, like this: <CRLF>.<SPACE><CRLF>

Or maybe it was a space before the period? I'm too lazy to look it up now,
I'm sure it is one or the other though heh. Just remember if you use a
similar mechanism yourself, that it is something you would have to take into
consideration also.
 
D

Dmitry Akselrod

Thanx Everyone for all your suggestions and explanations. I really
appreciate it.

I ended up appending two End Of Transmission ASCII characters (Chr(4)) to
the ends of all transmissions. I haven't had any problems since. Since I
was parsing the transmissions with an xml parser, I had to remove the extra
couple of characters before doing so of course.

Thanx again,

Dmitry
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top