| You are not logged in Either you are not a registered user, or your previous session has timed out. |
|||||||
| Home | Jokes | Media | Photo | Travel | Community | Programs | Resume |
| Programs Submenu: Tcl Tips | Projects  | |||||||
Sockets are used in all kinds of network programming, to allow communication between two computers, or between two programs on the same computer. The socket model is used extensively in TCP/IP communication. Typically, some program, a server, listens to a particular port number. When some program, a client, initiates a connection, the server "answers" and starts reading information from the client, and writing more information when necessary, much like reading from standard input and writing to standard output, or reading/writing from a file. In fact, socket communications in Tcl are NO MORE DIFFICULT than reading from a file or reading from a command pipeline, and operation almost exactly the same.
set trigger 0 set s [ socket -server openchan 5000 ] vwait trigger
The first command opens a socket to port 5000 (usually only ports below 1000 are reserved for system, i.e. root, use). When a client connects, the argument to -server is invoked, in this case the procedure "openchan". The parameters of the file handle for the connection, the address and the port of the client are automatically passed in. The second command is a "vwait" which will suspend execution of the program until the variable $var changes.
I'll show the openchan procedure later in this document. Suffice it to say that this procedure should be made to set up the channel parameters or maybe initialise some variables. Also, it should set up some method of recieving/parsing data from the client, and returning the results.
For simple testing, I often use the very normal unix "telnet" command. If I have a server waiting on port 5000, for example, on the same machine that I want to run the client on, I just say
telnet localhost 5000If I was using the server shown above, this is what the results would look like.
Client side:
{pickles:~} telnet localhost 5000
Trying 127.0.0.1...
Connected to c55106-a.rchdsn1.tx.home.com.
Escape character is '^]'.
Server ready.
Server side:
{pickles} ./server.tcl
Connection accepted 127.0.0.1:1174 (sock4)
This is great for simple testing, but for production use or extended debugging you'll probably want to make your own client. Of course, you don't HAVE to use Tcl, as the telnet example shows. But it is pretty convenient, so why not?
Here is a very simple client, that simply opens a connection to the server and merely listens.
set s [ socket localhost 5000 ]
while { [ gets $s line ] != -1 } {
puts $line
}
Here is the "openchan" that I almost always use, with a little modification.
proc openchan { chan address port } {
# Set up the channel parameters
fconfigure $chan -blocking 0 -buffering none
# whenever the channel is readable, run command
fileevent $chan readable "readchan $chan"
puts stdout "Connection accepted $adress:$port ($chan)"
puts stdout "Connection accepted $adress:$port ($chan)"
puts $chan "Server ready."
}
This openchan procedure configures the channel to be non-blocking. This is good because it means when you try to read/write from the socket channel the rest of the program won't have to wait for the I/O operation to complete. Then a "filevent" command is issued, setting up what to do when input is available on the channel. This is necessary, because in non-blocking mode, if you try a gets when there is no information, you get nothing back, the command just exits immediately. You could probably keep trying a gets until you got something, but this is pretty much a waste of time. Instead, the fconfigure command makes sure whenver there is data on the input of the socket, the procedure readchan is invoked, along with the channel file handle. This makes the program "event driven", i.e. whenever an event (input) happens, the program will automatically respond. This works with any number of simultaneous clinets; they will all get handed a unique file handle, and have a seperate event handler registered on their input. The example at the end of this section will demonstrate this better.
Take a look at the source for this little application.
This is a very simple application but it's a great starting point for a Tcl server. I'm not including any kind of client here, but it should be clear from my very simple client above how to make one.
The server responds to three commands and ignores everything else.
It might be a fun project to extend the server and make a client. The clients would connect, get the current time, and set the local system clock accordingly (through an exec call to the unix command "date" or something). Thus you could have a lot of clients all synchronizing their time to one server. This could be useful for maintaining accurate time between many machines in a network. Of course, it would probably be best to send the output of "clock seconds" with no modifications, since this would be easier for the client (written in tcl) to use.
Sample output of the program (from the client side).
{pickles:~} telnet localhost 5000
Trying 127.0.0.1...
Connected to c55106-a.rchdsn1.tx.home.com.
Escape character is '^]'.
Server ready.
time
Current time is: Sun Oct 03 22:35:26 CDT 1999
time
Current time is: Sun Oct 03 22:35:29 CDT 1999
exit
Goodbye sock4
Connection closed by foreign host.
Since I used the "exit" command, the server quit also.
| This document last modified: Friday, November 05, 2004 | me@rustybrooks.com |