meta data for this page
Network programming @ Noppa | @ wiki - Updated — Jussi Laakkonen 2012/10/11 17:25
Updates:
27.8.2012: Initial version.
28.8.2012: Updated the game listing feature description. Added commands.
28.8.2012: Change in requirements: IPv4 only (IPv6 = optional).
11.10.2012: Added: you may use connected UDP sockets.
Assignment4: Multicast Game announcement system & tic-tac-toe
The fourth assignment is to implement a peer-to-peer game announcement-like system using multicast and UDP protocol, use IPv4 only. OPTIONAL: implement in IPv6 (not sure if IPv6 multicast works in 6218). There is no need to build separate server and client, you need only to implement one application that fulfills both tasks. Every client connects to a multicast group and can send requests to multicast group members and also receive the replies for these requests via multicast.
Description
The client first joins to specified multicast group and requests all available games. When a reply is received all available games are presented to user and the user makes the selection. After this the game can be played between peers.
Client must not crash if something else (that is not specified in the protocol) is received from other members of the multicast group.
Client must inform the user if multicast group cannot be joined. Client must not crash because of the invalid input given by user.
Searching for games and joining
Every client can send a WHOIS
request to multicast group address, every client who is in the same multicast group that is not currently playing replies with HOSTINFO
that contains a port number. The client who replied has to have this port open and to be able to receive UDP traffic in that port. The client who sent the request can then send direct requests to the replied clients using this port.
The client makes the WHOIS
request right after it has joined to multicast group. This can be afterwards commanded by the user. The client shows all responses that it can receive during 5 seconds. After this user can either select a server or do another request.
OPTIONAL : Each client maintains the list of available games (list is updated always when HOSTINFO
is received via multicast) and this list must be printed to user when requested via CLI. List must not contain duplicates, we can assume that the port numbers reported in HOSTINFO
do not change during the lifetime of the client (when started the client should stick to the port number that was given as parameter).Remove games that reject player (game full, game already running) from the list.
The Game
The game that is played is tic-tac-toe. The “server” (client A) is the client who has the open port and the connecting one is the “client” (client B), who also gets to start the game.
The game is played between 2 players and in three by three (3×3) grid where indexes are from 0 to 2. Player has to give 2 coordinates (e.g. '0,1') for his/her marker. Position 0,0 is the top left corner.
The client acting as server (client A) awaits for connections in the port that was sent in the reply. When some another client (client B) connects with HELLO
message the client A replies with HREPLY
. If the client A has already started a game with some other client ERROR
with appropriate code is sent instead.
After this the game begins and the client B sets the first mark (char x) with POSITION
message. Client A replies with GRID
message or with ERROR
if mark cannot be placed or WINNER
message if the client B won the game. If the ERROR
is sent the client B has to select a new position for his/her mark.
After client B has set the mark then the client A can select a position for his/her mark (char o). After it has been set via CLI the client B sends GRID
message to client A who can set another mark. The client B can also reply with WINNER
message if the client A won the game.
The GRID
message contains the whole game grid and marks in different coordinates. The WINNER
message means that the game has ended and clients can return to game announcement state. The client must show which player won (which mark).
While the game is running the connection attempts (HELLO
messages) received from some other address are to be responded with ERROR
messages.
Requirements
- No centralized server, use the multicast address.
- Joining to multicast group and leaving from multicast group. One group per client.
- Sending messages to multicast group.
- Listening for incoming messages from the group.
- Send numbers in network order where applicable (do not send them as characters!)
- Do not use
fork()
or threads. - You may use connected UDP sockets here. Remember the limitations. [update]
- Implement client:
- Start:
./gameclient -m <multicast address> -p <port> -o <open port>
- <multicast address> - Address of the multicast group
- <port> - Port number for multicast announcement
- <open port> - Port to listen on incoming game data
- Commands:
- /search - do a search request (send
WHOIS
) - /games - show list of games
- /join <server order number> - join to specified server (server order number shown by the client)
- /grid - show latest grid
- /place <x> <y> - place own mark into x,y position, where x = x coordinate, y = y coordinate
- /quit - quit and leave the game
Protocol
Multicast
Following messages are sent/received via multicast.
WHOIS
unsigned 8bit int |
---|
0x00 |
A query message sent to the multicast group address.
HOSTINFO
unsigned 8bit int | unsigned 16bit int |
---|---|
0x01 | port number |
Reply to WHOIS
message, sent to multicast group address. Contains the number of that port that is open on the client who sends this reply. This is not sent when the client is currently playing.
UDP - directly
Following messages are exchanged between two playing clients. These messages should not be accepted (except HELLO
) from any other than the active peer.
HELLO:
unsigned 8bit int |
---|
0x02 |
Hello message sent by client B to client A as first message.
HREPLY:
unsigned 8bit int |
---|
0x03 |
Reply message to HELLO, sent by client A to client B when client B was accepted.
POSITION:
unsigned 8bit int | unsigned 8bit int | unsigned 8bit int |
---|---|---|
0x04 | x coordinate | y coordinate |
This message tells that in which position client B wishes to put his/her mark on the grid. Sent by client B to the client A.
GRID:
unsigned 8bit int | char | char | char | char | char | char | char | char | char |
---|---|---|---|---|---|---|---|---|---|
0x05 | mark at 0,0 | mark at 0,1 | mark at 0,2 | mark at 1,0 | mark at 1,1 | mark at 1,2 | mark at 2,0 | mark at 2,1 | mark at 2,2 |
The playing grid
x
= client Bo
= client A-
= empty
Sent after POSITION
message when the mark can be placed. Sent also after client A has finished putting his/her mark, which also acts as an indicator for client B that he/she can put next mark.
WINNER:
unsigned 8bit int | 1 char |
---|---|
0x06 | players mark as character |
Message that indicates the winner of the game, includes the mark of the winning player.
QUIT
unsigned 8bit int |
---|
0x07 |
When either of the clients decides to quit prematurely. This means that receiving client can return to game announcement state.
ERROR:
unsigned 8bit int | unsigned 16bit int |
---|---|
0x08 | error type |
- Error types
- 1 = game full
- 2 = invalid position
- 3 = no active game (playing but not acting as “server”)
Error message, sent by client A when game was full or given position was invalid (invalid coordinates or position taken). This is also sent, e.g.,when client B gets HELLO
message from client C into game port while already playing a game with client A.
Sequence diagrams
Multicast and joining to game
Game process
Additional notes and hints
- Read and learn: http://www.tldp.org/HOWTO/Multicast-HOWTO.html for IPv4
- Oracle.com Programming Interfaces Guide documentation for SOLARIS (yes, SOLARIS is UNIX and Linux is not UNIX but these pages explain multicast in informative manner):
- For IPv4:
- For IPv6:
- Note the address struct usage with multicast addresses. Be careful not to lose the address information while reading data from multicast socket.
- Hints:
bind()
sendto()
recvfrom()
socket()
select()
setsockopt()
getsockopt()
getaddrinfo()
freeaddrinfo()
getifaddrs()
htons()
ntohs()
htonl()
ntohl()