Transmitting user data using TCP is trickier than doing that over UDP, mainly because of TCP's reassembly queue is only available for FullTcp. We deal with this problem by abstracting a TCP connection as a FIFO pipe.
As indicated in section 40.2.4, transmission of application data can be implemented via agent upcalls. Assuming we are using TCP agents, all data are delivered in sequence, which means we can view the TCP connection as a FIFO pipe. We emulate user data transmission over TCP as follows. We first provide buffer for application data at the sender. Then we count the bytes received at the receiver. When the receiver has got all bytes of the current data transmission, it then gets the data directly from the sender. Class Application/TcpApp is used to implement this functionality.
A TcpApp object contains a pointer to a transport agent, presumably either a FullTcp or a SimpleTcp. 41.1(Currently TcpApp doesn't support asymmetric TCP agents, i.e., sender is separated from receiver). It provides the following OTcl interfaces:
In order to send application data in binary form, TcpApp provides a virtual C++ method send(int nbytes, int dsize, const char *data). In fact, this is the method used to implement the OTcl method send. Because it's difficult to deal with binary data in Tcl, no OTcl interface is provided to handle binary data. nbytes is the number of bytes to be transmitted, dsize is the actual size of the array data.
TcpApp provides a C++ virtual method process_data(int size, char*data) to handle the received data. The default handling is to treat the data as a tcl script and evaluate the script. But it's easy to derive a class to provide other types of handling.
Here is an example of using Application/TcpApp. A similar example is Test/TcpApp-2node in ns/tcl/test/test-suite-webcache.tcl. First, we create FullTcp agents and connect them:
set tcp1 [new Agent/TCP/FullTcp] set tcp2 [new Agent/TCP/FullTcp] # Set TCP parameters here, e.g., window_, iss_, \ldots $ns attach-agent $n1 $tcp1 $ns attach-agent $n2 $tcp2 $ns connect $tcp1 $tcp2 $tcp2 listen
Then we create TcpApps and connect them:
set app1 [new Application/TcpApp $tcp1] set app2 [new Application/TcpApp $tcp2] $app1 connect $app2
Now we let $app1 be sender and $app2 be receiver:
$ns at 1.0 "$app1 send 100 \bs"$app2 app-recv 100\bs""
Where app-recv is defined as:
Application/TcpApp instproc app-recv { size } { global ns puts "[$ns now] app2 receives data $size from app1" }
Tom Henderson 2011-11-05