This demo shows how to send and receive data using the
SendData and GetData methods.  It started out as an example
for someone who needed to send login info to another computer.
I decided to turn it into something of a tutorial on good
sockets programming practices.

Both the client and the server are running on the same PC.

The Client stores the input UserId and PassWd in the
Login record and sends it to the Server.

The Server accepts the record from the Client and displays
the UserId & PassWd.  When the Accept or Reject command
button is clicked, the appropriate value is assigned to
UserOK and the record is sent back to the Client.

The Client then displays the corresponding message in a
label.

One thing that I have noticed in posts is that many who are
new to sockets programming seem to believe that they must
close the socket after sending a message.  If the intent is
to pass mulitple messages back and forth, then it is best to
make the connection persistent.  Do not close it until you
are ready to terminate.  Think of the connection as a phone
converstaion.  Either side can 'speak' when and as often as
needed.  To prove this, once the client has sent a login
request, click Accept on the Server, then click Reject, then
Accept, etc., etc..

Another thing that you might want to watch is the scenario
wherein one side goes away in the midst of a connection.  Let's
force an abnormal termination of the server by closing it after
conncting to the client.  Notice that the client will briefly 
display "Peer is closing" before it closes the socket on its
own end.  After the client closes its socket, click the Connect
button.  Error 10061 is returned when there is nothing listening
on the IP address:Port # specified in the connect request.

WARNING!!!
Try to use only intrinsic data types in user defined structures,
especially for cross-platform & cross-language communication.
DO NOT use other user defined structures, byte arrays or
undimensioned strings in your user defined structure or you may
have problems: UDTs may be a byte or 2 larger than defined, a 
byte array is defined as vbArray + vbByte (so it will be 1 byte
larger than what you declare it) and an undimentioned String is
actually a pointer to a String and will be 4 bytes in size.  An 
address to a string on your computer won't be of much use to the
computer receiving the address.

The following examples should demonstrate how to pass user
defined data types. They are taken from a VB client that is
sending/receiving data to/from a server written in C and
running on a Tandem platform.

Public Type dclStdHeader
            ttl_len         As Long        ' long  ttl_len;
            msgtype         As Long        ' long  msgtype;
            orig_id         As Long        ' long  orig_id;
            seq_num         As Long        ' long  seq_num;
            tran_type       As Long        ' long  tran_type;
            curr_wndw       As Long        ' long  curr_wndw;
            curr_req        As Integer     ' short curr_req
            user_def        As String * 26 ' char  user_def[26];
        End Type
Public Type dclNodeStatus
            desc            As String * 8  ' char  desc[8];
            type            As Integer     ' short type;
            monicnt         As Integer     ' short monicnt;
            proccnt         As Integer     ' short proccnt;
            excpcnt         As Integer     ' short excpcnt;
       End Type
Public Type dclMonitorRep
            rep_hdr         As String * 52 ' holder for dclStdHeader
            repid           As Integer     ' short rep;
            sysname         As String * 8  ' char  sys[8];
            lines           As Integer     ' short lines;
            typeline(15)    As String * 16 ' holders for dclNodeStatus
       End Type

Public MonitorReply         As dclMonitorRep
Public StandardHeader       As dclStdHeader
Public NodeStatusLine       As dclNodeStatus

CopyMemory StandardHeader, _
           MonitorReply.rep_hdr, _
           Len(StandardHeader)

For i = 0 To 15
    CopyMemory NodeStatusLine, _
               MonitorReply.typeline(i), _
               Len(NodeStatusLine)
Next

*=======================================================================*
Updates

22 Mar 2002 - added examples of little-endian and big-endian byte order.

x86 based computers store Integers and Longs in what is called 
little-endian format in which the byte order is reversed from what you 
would expect.  The value 45693, or hex B27D is stored in memory as 7DB2.  
The little end is stored first.  This will cause a problem if the 
receiving computer stores numbers big end first.  What you must then do 
is send the values in what is called network-byte-order.  The receiving
computer should then convert network-byte-order values to it's  
host-byte-order.  If both sender and receiver use the same host-byte-order, 
then you don't need to do anything.  

A safe coding practice would be to always convert numbers to 
network-byte-order before sending and have the receiving side convert 
them to it's host-byte-order.

NOTE: network-byte-order is big-endian.

Fortunately, there are API calls to handle this.  
 ntohl - network to host long (for longs)
 ntohs - network to host short (for integers)
 htonl - host to network long (for longs)
 htons - host to network short (for integers)

Declare Function htons 
                 Lib "ws2_32.dll" (ByVal hostshort As Integer) As Integer
Declare Function htonl 
                 Lib "ws2_32.dll" (ByVal hostlong As Long) As Long
Declare Function ntohs 
                 Lib "ws2_32.dll" (ByVal netshort As Integer) As Integer
Declare Function ntohl 
                 Lib "ws2_32.dll" (ByVal netlong As Long) As Long

              