TCP Programming
Chat Server

Modified

This exercise is designed to illustrate and provide practice for network programming tasks common to many server applications. The format of the exercise is:

  1. begin with a very simple server application
  2. identify a problem or reasonable improvement
  3. propose and design a solution
  4. implement the solution
  5. test the implementation.

Chat Server - Chat servers connect two or more clients so that the input of one client is output to all other clients. Attempt number zero of a chat server that reads a line of text from the keyboard and prints to the screen is below. No networking is done so the server isn't really a server but does illustrate some of the general structure of a chat server.

  1. Copy and paste the following program into an editor.
  2. Save as:
  3. Execute in a Command Prompt window by:
  4. Type a few lines into the window.
# chatserver0.py

class server0 :
   def run(self) :
      print 'Connected'

      while True :
         From=raw_input()          # Read line
         if not From : break
         print From, '\n'

       print 'Disconnected\n'

server0().run()                     # run server

 

Try
  1. Open Python: Start | Programs | Python | IDLE
  2. In Python:
    • File | New
  3. Copy, paste and save the above file as:
    • chatserver0.py
  4. F5 to run

Python Programming Points
 

  • server0( ) - Constructs a server0 object.
  • server0( ).run( ) - Calls the run method on the server0 object
  • if not From : break - Exits while loop when empty line entered.
     
  • From=raw_input( ) - Reads a line of text from the keyboard.
     
  • print From - Outputs From to the screen.

Exercise 0 - Obviously chat version 0 needs networking. Try to identify points within the program where:

  1. the server waits for the client connection,
  2. the input of the connection is constructed,
  3. the output of the connection is constructed,
  4. the client input is read,
  5. the client output is printed.

Exercise 1 - Chat server version 1 implements network communication with a TCP client. Test the chat server by:

  1. Copy and paste the following program into an editor.
  2. Save as:
  3. Execute in a Command Prompt window by:
  4. Run a client telnet session to connect with the chat server in another Command Prompt window by:
  5. Type a few lines into the telnet window.
  6. Determine by testing:
    1. whether more than one client telnet sessions can be handled by the chat server at the same time,
    2. whether it continues after the client connection is closed,
    3. other server weaknesses.


Comparison of Non-networked and Networked Program

# chatserver0.py

class server0 :
   def run(self) :
   print 'Connected'

   while True :
      From=raw_input()          # Read line
      if not From : break
      print From, '\n'

   print 'Disconnected\n'

server0().run()                     # run server
# chatserver1.py

import socket

class server1 :
   def __init__(self, (socket, address) ):
      self.SOCKET=socket
      self.ADDRESS=address

   def run(self) :
      print 'Connected ', self.ADDRESS 

      while True :
         From=self.SOCKET.recv(1024) # Read from client
         if not From : break
         self.SOCKET.send(From)

      self.SOCKET.close()
      print 'Disconnected ', self.ADDRESS

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 8888))
s.listen(1)

server1( s.accept() ).run();      # Wait for connection/run server

 

Try
  1. Open Python: Start | Programs | Python | IDLE
  2. In Python:
    • File | New
  3. Copy, paste and save the above file as:
    • chatserver1.py
  4. Press F5 to run.
  5. Start | Run
    • telnet localhost 8888
    • Enter a few key strokes to echo back
    • Ctrl ]
    • quit

Python Programming Points
 

  • import socket - Import the socket library module.
     
  • def __init__(self, (socket, address) ): - Constructor for server1 objects.
     
  • s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - Constructs a socket object assigned to s
     
  • s.bind(('', 8888)) - binds s to port 8888.
     
  • s.listen(1) - listen for 1 connection to s.
  • s.accept() - Waits for a connection on socket object s. Returns a socket when the connection is completed.
  • server1(s.accept( )) - Constructs a server1 object using the socket connected to the client.
  • server1(s.accept( )).run( ) - Executes the server1 method named run.
  • From=self.SOCKET.recv(1024) - Receives a string from client through the socket object self.SOCKET.
     
  • if not From : break - True when client disconnects, breaks out of the while.
     
  • self.SOCKET.send(From) - Sends the string From through the socket connection to the client.
     
  • self.SOCKET.close() - Closes the connection between client and the server.

Exercise 2 - One weakness is that the server terminates when the client connection is closed. The server should wait for another connection rather than terminating.

  1. Propose a solution,
  2. implement the solution, the instructor will help.
  3. Name the new program file:
  4. Name the server class:
  5. Test as before. You'll need to use the Task Manager to kill Python.
  6. Side-by-side comparison of chatserver1 and chatserver2.

Exercise 3 - A serious weakness for the chat server is that only a single client can be connected at a time. The server should allow multiple simultaneous connections.

  1. Propose a solution,
  2. implement the solution, the instructor will help.
  3. Name the new program file:
  4. Name the server class:
  5. Test as before. You'll need to use the Task Manager to kill Python.
  6. Side-by-side comparison of chatserver2 and chatserver3.

Exercise 4 - The server still has a serious weakness in that the multiple clients can't chat to each other!

  1. Propose a solution  keeping in mind that each client has an independent connection to the server,
  2. implement the solution, the instructor will help.
  3. Name the new program file and class:
  4. Name the server class:
  5. Test as before. You'll need to use the Task Manager to kill Python.
  6. Side-by-side comparison of chatserver3 and chatserver4.

Exercise 5 - The server should usually behave as expected but has a potential hazard. Each client connection is running in a separate thread on the server. When multiple clients attempt to connect at the same time, updates to the vector holding the client connection is in a race condition. One thread could begin accessing the vector, be suspended, and another thread undo or corrupt the vector. 

  1. Identify the hazard,
  2. propose a solution,
  3. implement the solution, the instructor will help.
  4. Name the new program file and class:
  5. Name the server class:
  6. Test as before. You'll need to use the Task Manager to kill Python.
  7. Side-by-side comparison of chatserver4 and chatserver5.