Introduction
这是接之前作业的第四部分,这部分主要用xterm来实现用户和用户之间的聊天协议,涉及到的知识点有domain socket, fork, exec,
pipe, socketpair。
此外,还需要处理network programming中常见的网络异常情况,如client crash, error termination等。
User to User Chats
In this part you will be enhancing your client to allow for communication
between other clients. In order to separate individual user to user chats, you
will need to implement a chat executable program which your client will
execute as child processes. Using the xterm program in tandem with this chat
executable you’ll be able to create a client that spawns new windows as needed
to display chats. The behavior will emulate what you may be familiar with on
facebook or google hangouts functionality in terms of automatically spawning
new small windows dedicated for chatting as opposed to monopolizing the user’s
entire view of the screen.
When a client wants to begin a chat session with another user, they type into
the client window on stdin the client command /chat. This will trigger the
client to send to the server a new verb, MSG. The MSG verb will be used for
communication of ALL chat messages between the server and client. Let’s
consider an example:
- Paul initiates chat using the /chat command, the message is formatted into the MSG \r\n\r\n protocol and sent to the server.
- When the server receives the MSG verb, it sends the same message back to both the To and FROM user.
- When Paul’s and Neal’s client receive the MSG \r\n\r\n back from the server, the client program will create a UNIX Domain Socket to share with the child process (for the pop-up chat window) to communicate over, then fork and execv an xterm terminal which will run your ./chat program.
The chat program is a simple program which takes input from stdin and sends to
the Client program, prints on stdout messages from the client program, and
handles the command /close which terminates the child process (same as closing
the terminal window).
This is the initial creation of all user to user chats. Once both users have
an xterm chat window open for communication, the users can freely type
messages to each other. Incoming messages should be proceeded by the > symbol
and outgoing messages by < in the chat window. With each message entered in
the xterm on stdin, the chat program should relay the information to the
client through their Unix Domain socket. The client then converts the message
into the Wolfie Protocol MSG verb and sends to the server. The below figure
illustrates the steps.
A user can close a chat window at anytime using either the close button on the
xterm window or by using the command /close. When the window is closed on one
client it has no impact on the client who was chatting with the user. In the
figure below Paul closed the chat window but Neal still has it open. When Neal
types a message to Paul it is sent to the server (Step 1). The sewer will
forward the message back to Paul & Neal (Step 2). Since Paul has no existing
window, his client creates a new window and displays the message. Neal’s
client will just display the message since the xterm is already open.
Paul closed the chat window and then wants to send Neal a new message. To
initiate the chat again, he would need to type /chat command in his client.
This will send the MSG verb to the sewer (Step 1 in figure below). Upon the
server’s response, Paul’s client would spawn a new chat window. Neal and
Paul’s chat windows will then both display the
Overall, the protocol MSG verb is generic. The server has no knowledge of the
chat windows open or closed. It is the client program’s responsibility to
open, close, and manage the chat windows. In this way, it doesn’t matter if
the xterm window is closed because every time MSG is received the client will
check to see if a window already exists for communicating with the user and
if not it will fork and exec a new xterm process to become the window needed
for communication. If the window does exist then the message is passed through
the Unix domain socket and displayed appropriately on the chat window.
If one of the user’s disconnects from the server or does not exist, but a
message is sent to this user, the server will respond with an ERR message.
Added Client command
/chat
The /chat command requires the name of the user to send the message to and the
message to be sent. The client program will send to the server the MSG verb to
communicate the message to the other user.
/logout
Update the functionality of the command to now additionally close all the chat
windows and all file descriptors prior to exiting the client program.
Chat Program
Usage:
./chat UNIX_SOCKET_FD
UNIX_SOCKET_FD The Unix Domain File Descriptor number.
When the server sends MSG verb to your client it should fork and exec xterm,
which in turn will exec your chat program in a basic terminal. This will act
as the interface to communicate with another user much like chats on Facebook
or hangouts work. These will act as the small popups to chat in while the
client remains the manager for the connection with the server. The chat
program will use Unix domain sockets to communicate with the parent client
process. Using socketpair() you can declare two anonymous sockets and pass the
file descriptor to the chat program as an argument. You can also declare the
sockets as you would normally using socket(). In either case you must use
AF_UNIX as the domain.
xterm is a powerful terminal emulator as it allows for a lot of customization
using command line arguments. You should study the man page for xterm to see
what arguments will help make your program as easy to use as possible. To get
you started, the format to fork and exec the ./chat program in xterm is as
follows:
Example execution string: “xterm -geometry 45x35+%d -T %s -e ./chat. %d”
Each of the arguments have the following meaning.
- -geometry geometry: This argument allows you to set the size and location of the xterm window opened. Geometry format is described here under “geometry specifications”. However, all you really need to know is that is takes the format WIDTHxHEIGHT+XOFF+YOFF where width and height are in characters and XOFF and YOFF is in pixels. In the suggested execution string above you can see that you can omit the YOFF value and you can use sprintf to set the XOFF so the windows spawned are not stacked on one another.
- -T string: With this flag you can set the title of the string to the username being communicated with so the user has a quick reference of which window is chatting with whom. Use %s format specifier to insert the username for the chat.
- -e program [arguments … ]: finally there is the most important flag. -e specifies the executable to be run when the terminal opens. The arguments to the program follow immediately after as you would type them in the terminal. The execution string shows how you would pass the unix domain socket file descriptor. Use %s format specifier for the file descriptor of the Unix domain socket.
The chat program should prompt the user for input, anything the user types in
followed by pressing the enter-key should be considered a message with the
exception of the /close command. The /close command simply closes the window
and the Unix domain socket in the parent. There is no protocol messages that
need to be exchanged with the server when this command is used. The Client
forwards each MSG received to the corresponding chat window via each open
chat’s Unix domain socket.
The protocol has new verbs that must be implemented to support these user
features. As we have seen in the figures, the MSG verb will deliver the
information of who the message is to, whom it is from, and the message being
sent. Additionally, add a new verb, UOFF, which will be used to notify ALL
clients connected to the server of a user logging out or disconnecting from
the server.
Client crash or error termlnatlon
Crashes happen so the UOFF verb should handle both the case of a client
disconnecting and of a client logging off. If someone’s chatting partner
disconnects and the chat window is still open for that user, when the UOFF
verb is received, the chat window should print a message that informs the user
of the disconnection. The xterm window should then close on any key press.
This is to prevent the user from attempting to send anything to a disconnected
user. Think about how the server can handle errors when trying to pass along
user messages, and accordingly turn that error into a UOFF broadcast verb to
notify all clients of the user’s disconnection.
Server
On the server side the communication threads must handle receiving and sending
messages to the proper clients using the MSG protocol defined in the prior
figures. The server also must handle forwarding the UOFF verb to all still
connected clients when a user disconnects or logs off the server.