To gain experience writing a socket program interacting with a server using a protocol.
For this project, you will write a chat client which will connect to a chat server. Your client will allow users to connect to the chat server, create or join chat rooms and chat with other users.
You will connect to a server running at 34.73.23.1 on port 5220. This is a very simple chat server developed for this project. Your chat client should connect to this server and, following the protocol described below, let the user chat with any others logged in.
Note that this server will be used by others in this class, and they can see what you are sending (if theirs is working anyway)!
Right after you connect to the server, you will be in a "lobby" of sorts. At that point you can do one of two things:
After the user has joined a room, they must choose a nickname. This can be done by sending "/nick NAME" to the server where NAME is the nickname the user has chosen. The server will send "0" to indicate success, "1" to indicate the request was formatted incorrectly, or "2" to indicate that the name is taken (all nick names in a room have to be unique).
Once they have picked a name, they will be in the chat room. At this point, the server will send the client messages whenever anyone talks. Likewise, the client can send the server a message at any time. These messages will just be plain strings.
From within the room, there are two "special" messages the client can send to the server:
You can assume all messages from the server will be 1024 bytes or fewer. The server makes the same assumptions about what you send.
You have flexibility in how the interface to your program should work, but you need to make it clear to the user how to do all of these things. You also should not just dump the server messages (like "1" or "2" for errors), but should give a sensible message.
select
One issue you will run into with writing the client, is that we must
read from both the server, with our socket, and also the user's input.
The issue is that the socket recv
method, and the Python
input
function are blocking.
This means code like this won't work well:
# read from server
mesg = sock.recv(1024)
# read from user
in = input()
When recv
is called, it will block, meaning it won't return
until the socket actually sends something. If the socket sends data before the
user, that's OK. But if not, our code won't get the user's message until the
server sends. Flipping them in the other order makes a similar issue.
Instead we need to wait for either one to have data available and handle
whichever one is ready first. This is done with select
. We must
first import the select
module.
The function works by taking three lists. The first is the list of things we want to read from. The second is a list of things we want to write to. The third is a list of things we might expect errors on. It returns three lists as well, which are those things which are ready. If we only care about reading from a socket and the user, we can call it like this:
# for the select function
import select
# for the stdin file
import sys
# wait for either our socket or user
reads, writes, errors = select.select([sock, sys.stdin], [], [])
The select function will block until one of the things is ready. In this
case, when sock and/or sys.stdin are ready to be read. The reads
variable will be a list of things waiting to be read. If it contains
sock
, then we can recv from the socket. If it contains
sys.stdin
, we can get input from the user right away.
When writing your program, also be sure to:
To submit your program, email the program file to ifinlay@umw.edu.
Copyright © 2024 Ian Finlayson | Licensed under a Creative Commons BY-NC-SA 4.0 License.