One way to handle this without having to involve the parent process is to bind another program to each connection to handle the user's requests. For example, when you are on a graphical environment, there are seperate programs in each window. Each program can accept data from the keyboard and print data to the screen. The currently active window (program) is the one that receives the data from the keyboard, so in that fashion the keyboard can be shared among multiple programs by changing which window is active. Likewise, each program only prints data to the screen within their window, so standard out can be shared without any entanglement of output.
From the network server's perspective, there is not so much standard in and standard out as there is incoming data on a socket and data to send out over a socket. The bound process and client-side program will handle converting network data into standard in and standard out. By binding a process to each child to handle the data, the network server no longer needs to process the data coming in and out. It can focus purely on delivering the data and managing the children processes. The network server accomplishes this by mapping the data coming into the socket (recv()) to the standard in of the bound process. Likewise, it maps the standard out of the bound process to the data being sent out on the socket (send()). The bound process needs no knowledge of network sockets; it operates purely on standard in and standard out.
In this part of the lab, we will look at how three programs work together to provide such a system. These programs make a small, pared-down, simple shell over telnet. The code can be found in the lab code tarball. Compile the code with the commands:
make shell make telnet
s_daemon.c
is the server program. It accepts and manages
connections. It also spawns the simple shell program, s_sh.c
,
to interact with each connection. It is similar to daemon.c
from
Lab 5 except it spawns a new program for the children
instead of handling the data itself. It uses pipes to communicate with
s_sh
. The pipes do the mapping of socket data to standard in/out
as described above. select()
has been expanded to watch both the
sockets and pipes. See the function dialog_with_telnet()
for
these changes. The command to start s_daemon is:
s_daemon [-log]The optional log option will create a log, similar to
daemon.c
.
Run this command first and note the port number that it binds to.
s_sh.c
is a very simple shell. A shell is used to interact with
the system. It parses commands and command options, runs them and displays the
results. This program can parse a few commands such as cd, dir and pwd. It also
supports one * or ? wildcard per line. The comments section at the top of the
file lists more details on the capacity of this shell program. From
s_sh
's perspective, it is operating purely on data received from
standard in and writing out to standard out. This is then mapped by the pipes
created in s_daemon
to the network socket. You do NOT need to
run s_sh. When you connect to s_daemon, it will spawn a process for s_sh.
s_tlnt.c
is a simple telnet client. You can use the provided
telnet on Sleipnir instead of s_tlnt
to initiate the connection
to s_daemon
, but s_tlnt
gives you some additional
features and control over the processing of the network data. Some interesting
things to look at in the s_tlnt.c
code are
process_esc()
and the commandmode
jump target in
main()
. The process_esc()
function interprets basic
VT100/ANSI escape sequences. VT100 and ANSI are standards to control the
placement of the cursor on a text screen, colors, reverse colors, blinking
text, clearing the screen and other such functionality needed to create basic
text-based graphical interfaces. If you use Pine, you've seen VT100 and ANSI
in action. The commandmode
jump target can be reached by pressing
CTRL-T (the "escape character") while the program is running. This will bring
up the s_tlnt
prompt. Your connection will still be active
in the background while you give commands to the s_tlnt
program.
You can "close" an active connection, "return" to an active connection, "open"
a new connection, set s_tlnt
parameters, access a "help" screen
and see the "status" at the s_tlnt
prompt. The parameters can
enable features which will give more information about the data being passed
across the network, such as VT100 codes.
The command to start s_tlnt
is:
s_tlnt [-v] [-snoopy] hostname portThe v option will turn on verbose, which will give you detailed information about the execution of the program. You can also set "verbose" or "noverbose" at the
s_tlnt
prompt. The snoopy option activates transparent
mode, which gives information about telnet arbitration and shows all control
and 8bit characters. You can set "snoopy" or "nosnoopy" at the
s_tlnt
prompt. The hostname is the name of the host and the port
is the port number given by s_daemon
when you ran it.
s_tlnt -v -snoopy helios 23
. Do NOT
actually log in to Helios as that will send your password in plaintext.
Hit CTRL-T and then type "close" when prompted to log in. What do you see?
ps x
right after you've logged in to Sleipnir and
note what processes you have running.