...the client process opens a TCP connection to a server, at port number xx...In this lecture, we examine what this really means from the perspective of a programmer writing a TCP-based client or (more complex) a server.
In a major change from previous years, we will use the
Java programming language for our examples. Previously
we used C
, the standard system-level programming
language on Unix systems. You should be aware that the concepts we will
introduce in today's lecture were originally (like most Internet
protocols) developed in a Unix environment, and still retain some of
the flavour of Unix -- that is, when you occasionally wonder
why the designers took a particular approach, the answer is quite
likely "...that's how it's done in Unix..
Sockets (and the TCP software to which they form the interface) are implemented in all modern operating systems as system calls; that is, they form part of the operating system kernel. In modern object-oriented languages such as Java (and others), a socket class is implemented "on top of" these basic system-level services.
TCP sockets in Java are different for server and client processes. For a client process, a socket is created as follows:
This creates a new Socket object which is associated with a TCP connection to port 79 on ironbark. The newly created socket can be used as both an input and output stream, see next slide.Socket myclientsocket = new Socket("ironbark", 79);
finger
application protocol. If we send a text string containing a valid
username on ironbark, we should receive some interesting facts about
the user. Here's the Java code:
Note that this program only outputs the first line of the data returned from the server.import java.io.*; import java.net.*; class FingerClient { public static void main(String argv[]) throws Exception { String user = "pscott"; String response; Socket clientSock = new Socket("ironbark", 79); DataOutputStream toserver = new DataOutputStream( clientSock.getOutputStream()); DataInputStream serverReply = new DataInputStream( clientSock.getInputStream()); toserver.writeBytes(user + "\n"); response = serverReply.readLine(); System.out.println("Finger Reply: " + response); clientSock.close(); } }
getInputStream()
, and writing to
(via getOutputStream()
), the connected socket:
getInetAddress()
getPort()
getLocalPort()
import java.io.*; import java.net.*; class SillyServer { public static void main(String argv[]) throws Exception { String incoming; String outgoing; ServerSocket servSock = new ServerSocket(7277); while(true) { Socket connectedSocket = servSock.accept(); DataInputStream fromClient = new DataInputStream( connectedSocket.getInputStream()); DataOutputStream toClient = new DataOutputStream( connectedSocket.getOutputStream()); incoming = fromClient.readLine(); outgoing = incoming.toUpperCase() + "\n"; toClient.writeBytes(outgoing); connectedSocket.close(); } } }
Whilst the Java code for a multi-threaded server is too complex to
include into the lecture, the basic concept is that the
accept()
method returns a new, connected,
socket. A program can start up a new thread of
execution which handles communications using the connected
socket, whilst allowing the "main program" to again go back to
"accepting connections".
Conceptual Conundrum -- how can the newly-created program thread perform communications on (eg) port 7277 at the same time as the server is "waiting for connections" at the same port number? The answer to this is very subtle. In fact, an active TCP connection is characterised by a 4-tuple, consisting of the IP addresses of each of the computers involved, plus both of the port numbers (both client and server) in use. Because this 4-tuple is unique for every TCP connection (Exercise: why?), it's possible to have many server threads serving client requests simultaneously (or, more correctly, concurrently)
On the other hand, a C program to perform the same function is about 100 lines, not including comments...#!/usr/local/bin/perl use IO::Socket::INET; $sock = IO::Socket::INET->new(PeerAddr => 'ironbark', PeerPort => 'finger(79)', Proto => 'tcp'); print $sock "pscott\n"; while(<$sock>) { print; }