Hosted by |
|
Here is a small network server that illustrates the sophisticated I/O and socket facilities in Tcl. The server can accept connections from multiple clients. For each client, the server just echoes what a client sends it. Tcl manages all the I/O with different clients so the server does not have to block servicing a client or waiting for connections. You can use this server as the basis for almost any network service. First we present the program and a summary of the commands in it. After that we'll look at parts of the program in more detail.
The Server SocketA network server listens for connection requests from clients. The operating system creates a new socket connection between each client and the server, so the server can have several clients connected simultaneously. The Tcl socket -server command associates the server's listening socket with a callback that Tcl invokes when clients make connections. If you are familiar with the C-level socket APIs, Tcl socket command call hides all the details of the bind(), listen(), and accept() system calls: set s [socket -server EchoAccept $port] In this case, EchoAccept is called each time a client connects to the server. For this to work, Tcl must enter the event loop so it can wait for the connection requests. The vwait command is used for this purpose. It puts Tcl into the event loop until the variable is modified. In this case, we never plan to modify the variable, so we call it "forever". What is the Event Loop?The event loop is a facility built into the Tcl runtime. It lets you register Tcl commands that are called later when various events occur. Example events include socket connections, data ready on an I/O channel, timer events, and window system events like mouse motion and keyboard presses. There are two commands in the example that register event callbacks: the socket -server command described above, and the fileevent command described in the next section. The event loop needs to be active for the callbacks to work. If you use wish for a Tk application, then the event loop is active automatically. However, if you use tclsh then you must activate the event loop explicitly. The vwait command enters the event loop until a variable is modified. You can use it for a short-term wait that is ended by setting the variable, or you can wait indefinetly. Client ConnectionsThe EchoAccept command is called when a client connects to the server. Tcl adds three arguments to the command when it makes the callback: the new socket for the connection, the client's IP address, and the client's port. In the example, the client's address and port are saved in an array, and in general a server will keep some sort of state about each client. Line BufferingThe server puts the new socket into line-buffering mode so that each puts results in a network transmission. Otherwise Tcl buffers data until the buffer fills or a flush command is used. The fconfigure command sets up the buffering mode: fconfigure $sock -buffering line Event-Driven I/OThe EchoAccept procedure sets up another callback to handle the data from the client on the new connection: fileevent $sock readable [list Echo $sock] The Echo command is called when the server can read the socket. With fileevent the callback is a complete command that explicitly includes the new socket. The list command is used to create a well-formed Tcl command for the callback. End-of-File and ErrorsThe Echo command checks for end-of-file: eof $sock Then it reads a line from the socket and catches error that might occur: catch {gets file line} The first argument to catch is a script. Tcl will put the script through the normal evaluation cycle, so you can brace the whole script in curly braces. This example will run the gets command to read a line of input. That command could raise an error if the socket is in certain error states, so we put it inside a catch. Finally, the server replies simply by writing the line back to the client: puts $sock $line The Client SideThe client is very simple: set s [socket $host $port] fconfigure $s -buffering line The first command opens the TCP socket connection to the server (which triggers its call to EchoAccept). The second command sets up line buffering so each puts command results in a network transmission. As an experiment, you can also try using the Unix telnet program to connect to your server. Most telnets take the port number as the second argument: telnet hostname port |