TCP stands for
Transmission Control Protocol.
It is described in
STD-7/RFC-793. TCP is a
connection-oriented protocol that is responsible
for reliable communication between two end processes.
The unit of data transferred is called a stream,
which is simply a sequence of bytes.
Being connection-oriented means that before actually
transmitting data, you must open the connection between
the two end points. The data can be transferred in full
duplex (send and receive on a single connection). When
the transfer is done, you have to close the connection to
free system resources. Both ends know when the session
is opened (begin) and is closed (end). The data transfer
cannot take place before both ends have agreed upon the
connection. The connection can be closed by either side;
the other is notified. Provision is made to close gracefully
or just abort the connection.
Being stream oriented means that the data is an
anonymous sequence of bytes. There is nothing to
make data boundaries apparent. The receiver has no
means of knowing how the data was actually transmitted.
The sender can send many small data chunks and the receiver
receive only one big chunk, or the sender can send a big
chunk, the receiver receiving it in a number of smaller
chunks. The only thing that is guaranteed is that all data
sent will be received without any error and in the correct
order. Should any error occur, it will automatically be
corrected (retransmitted as needed) or the error will
be notified if it can't be corrected.
At the program level, the TCP stream look like a flat
file. When you write data to a flat file, and read it
back later, you are absolutely unable to know if the
data has been written in only one chunk or in several
chunks. Unless you write something special to identify
record boundaries, there is nothing you can do to learn
it afterward. You can, for example, use CR
or CR LF to delimit your records just like a flat text file.
At the programming level, TWSocket is fairly simple to use.
To send data, you just need to call the Send method
(or any variation such as SendStr) to give the data to
be transmitted. TWSocket will put it in a buffer until
it can be actually transmitted. Eventually the data will be
sent in the background (the Send method returns immediately
without waiting for the data to be transmitted) and the
OnDataSent event will be generated once the buffer is emptied.
To receive data, a program must wait until it
receives the OnDataAvailable event. This event is triggered
each time a data packet comes from the lower level.
The application must call the Receive method to actually
get the data from the low-level buffers. You have to
receive all the data available or your program will
go in an endless loop because TWSocket will trigger the
OnDataAvailable again if you didn't receive all the data.
As the data is a stream of bytes, your application
must be prepared to receive data as sent from the
sender, fragmented in several chunks or merged in bigger
chunks. For example, if the sender sent
"Hello "
and then "World!",
it is possible to get only one
OnDataAvailable event and receive
"Hello World!" in
one chunk, or to get two events, one for
"Hello "
and the other for "World!".
You can even receive more
smaller chunks like "Hel",
"lo wo" and
"rld!". What
happens depends on traffic load, router algorithms, random
errors and many other parameters you can't control.
On the subject of client/server applications, most
applications need to know command boundaries before being
able to process data. As data boundaries are not always
preserved, you cannot suppose your server will receive a
single complete command in one OnDataAvailable event. You
can receive only part of a request or maybe two or more
request merged in one chunk. To overcome this difficulty,
you must use delimiters.
Most TCP/IP protocols, like SMTP, POP3, FTP and
others, use CR/LF pair as command delimiter. Each
client request is sent as is with a CR/LF pair
appended. The server receives the data as it arrives,
assembles it in a receive buffer, scans for CR/LF
pairs to extract commands from the received stream, and
removes them from the receive buffer.
Using CR/LF as delimiter is very handy because you can
test your server using the well know application "telnet".