Source port (16 bits) Destination port (16) Length (16) (header + data, in bytes) Checksum (16) (optional (in case you're in a hurry); calculation involves a "pseudoheader" that incorporates info from the IP header)
Source port (16 bits) Destination port (16) Sequence number (32) (position of current chunk in the overall data stream) Acknowledgement number (32) (next chunk I expect to see from you) Hlen (4) (header length, in longs; we have options...) Reserved (6) (this space available) Code bits (6) (session control flags: URG, ACK, PSH, RST, SYN, FIN) Window (16) (I can handle this much more stuff from you) Checksum (16) Urgent pointer (16) (end of out-of-band data) [Options]
+---------+ ---------\ active OPEN
| CLOSED | \ -----------
+---------+<---------\ \ create TCB
| ^ \ \ snd SYN
passive OPEN | | CLOSE \ \
------------ | | ---------- \ \
create TCB | | delete TCB \ \
V | \ \
+---------+ CLOSE | \
| LISTEN | ---------- | |
+---------+ delete TCB | |
rcv SYN | | SEND | |
----------- | | ------- | V
+---------+ snd SYN,ACK / \ snd SYN +---------+
| |<----------------- ------------------>| |
| SYN | rcv SYN | SYN |
| RCVD |<-----------------------------------------------| SENT |
| | snd ACK | |
| |------------------ -------------------| |
+---------+ rcv ACK of SYN \ / rcv SYN,ACK +---------+
| -------------- | | -----------
| x | | snd ACK
| V V
| CLOSE +---------+
| ------- | ESTAB |
| snd FIN +---------+
| CLOSE | | rcv FIN
V ------- | | -------
+---------+ snd FIN / \ snd ACK +---------+
| FIN |<----------------- ------------------>| CLOSE |
| WAIT-1 |------------------ | WAIT |
+---------+ rcv FIN \ +---------+
| rcv ACK of FIN ------- | CLOSE |
| -------------- snd ACK | ------- |
V x V snd FIN V
+---------+ +---------+ +---------+
|FINWAIT-2| | CLOSING | | LAST-ACK|
+---------+ +---------+ +---------+
| rcv ACK of FIN | rcv ACK of FIN |
| rcv FIN -------------- | Timeout=2MSL -------------- |
| ------- x V ------------ x V
\ snd ACK +---------+delete TCB +---------+
------------------------>|TIME WAIT|------------------>| CLOSED |
+---------+ +---------+
; how far is the latest RTT sample off the weighted RTT average?
Diff = latestRTTsample - RTTaverage
; adjust RTT average for latest sample; the value of g determines how
; much weight is given to the current sample--1/8 is a common value
RTTaverage = RTTaverage + g * Diff
; figure out how far current Diff is off weighted Diff average, then
; recompute the latter; h again is a weighting factor, with a value
; of e.g. 1/4
DiffAverage = DiffAverage + h * (| Diff | - DiffAverage)
; compute timeout from averaged RTT and averaged variance
Timeout = (4 * DiffAverage) + RTTAverage
// Server
import java.net.*;
public class IncrementS {
private static final int BUFFLEN = 1;
private static final int PORT = 2411;
public static void main(String[] argv) {
try {
// reserve a port
DatagramSocket Ds = new DatagramSocket(PORT);
System.out.println("Listening at: " + PORT);
// reserve a data buffer to hold contents of inbound packet
byte[] ioBuffer = new byte[BUFFLEN];
// create a new packet object (pointing to the data buffer)
DatagramPacket inPacket = new DatagramPacket(ioBuffer, BUFFLEN);
// wait for request
Ds.receive(inPacket);
System.out.println("Connect from: " + inPacket.getAddress() + " with " + ioBuffer[0]);
// compute increment
ioBuffer[0] = (byte) (ioBuffer[0] + 1);
// make the response packet (point to data buffer; grab IP and port from the
// request packet to set up addressing in the response)
DatagramPacket outPacket =
new DatagramPacket(ioBuffer, BUFFLEN, inPacket.getAddress(), inPacket.getPort());
// the check is in the mail
Ds.send(outPacket);
}
catch (Exception e) { System.out.println("Oops."); }
}
}
// Client
import java.net.*;
public class IncrementC {
private static final int BUFFLEN = 1;
private static final String SERVERID = "bob.marlboro.edu";
private static final int SERVERPORT = 2411;
private static final byte XMITVALUE = (byte) 100;
public static void main(String[] argv) {
try {
// grab a local port (we never see--we don't care--what the port number
// actually is)
DatagramSocket Ds = new DatagramSocket();
// grab a data buffer
byte[] ioBuffer = new byte[BUFFLEN];
// fill the buffer
ioBuffer[0] = XMITVALUE;
// build a packet (point to the buffer holding the contents for the packet
// body, say how long the buffer is, say who the server is, say what port on
// the server to use
DatagramPacket outPacket =
new DatagramPacket(ioBuffer, BUFFLEN, InetAddress.getByName(SERVERID), SERVERPORT);
System.out.println("Sending: " + ioBuffer[0]);
// send the packet out the port
Ds.send(outPacket);
// make a new packet for the response (n.b., different constructor)
DatagramPacket inPacket = new DatagramPacket(ioBuffer, BUFFLEN);
// wait for our ship to come in
Ds.receive(inPacket);
System.out.println("Received: " + ioBuffer[0]);
}
catch (Exception e) { System.out.println("Oops."); }
}
}
// Client
import java.net.*;
import java.io.*;
public class NumSequenceC {
private static final int SERVERPORT = 5555;
public static void main(String[] argv) {
try {
Socket conn = new Socket("bob.marlboro.edu", SERVERPORT);
DataInputStream in = new DataInputStream(conn.getInputStream());
for (int i = 0; i < 1000; i++) {
System.out.println(in.readInt());
}
in.close();
conn.close();
}
catch (Exception e) { System.out.println("Oops."); }
}
}
// Server
import java.net.*;
import java.io.*;
public class NumSequenceS {
private static final int PORT = 5555;
public static void main(String[] argv) {
try {
// please listen at this port
ServerSocket s = new ServerSocket(PORT, 1);
// when a connection request comes in, set up the connection and
// hand it to us
Socket conn = s.accept();
// a little trickery so we can write in chunks of a specific data
// type (ints in this case) rather than raw bytes
DataOutputStream o = new DataOutputStream(conn.getOutputStream());
for (int i = 0; i < 1000; i++) {
o.writeInt(i);
}
// clean up
o.close();
conn.close();
}
catch (Exception e) { System.out.println("Oops."); }
}
}