A simple multithread pong game server using TCP/UDP.
Preview.PongServer.mp4
$ g++ -std=c++17 -O2 Source/*.cpp -o server
$ ./server
$ g++ -std=c++17 -O2 Tester/main_visual.cpp -o tester
$ ./tester
Change the content in "config.h" if you want to change.
Default : 9180
┌───────────────┐ Main Thread ┌───────────────┐
│ │ │ │
│ │ ┌──────Query──────┐ │ │
│ │ │ │ │ │
│ │ │ CreateSession ├─────────────────────────────────────────────────────►│ │
│ │ │ │ │ │
│ │ └────────┬────────┘ │ │
│ │ │ Recv Thread Input Processing Thread │ │
│ │ ▼ │ │
│ │ ┌──────Query──────┐ ─┬─ ─┬─ │ │
│ │ │ │ │ │ │ │
│ │ │ BeginRound ├─────────────┼─────────────────────────┼─────────────►│ │
│ │ │ │ │ │ │ │
│ │ └────────┬────────┘ │ │ │ │
│ │ │ │ │ │ │
│ │ │ │ │ │ │
│ │ │ ┌───────┴────────┐ │ │ │
│ │ │ │ │ │ │ │
│ │◄───────────┼──────────────┤ Relay state │◄───────────────┼──────────────┤ │
│ │ │ │ │ │ │ │
│ │ │ └────────────────┘ │ │ │
│ │ │ ┌────────────────┐ │ │ │
│ Players │ │ │ │ │ │ Game Server │
│ │◄───────────┼──────────────┤ Relay state │◄───────────────┼──────────────┤ │
│ │ │ │ │ │ │ │
│ │ │ └────────┬───────┘ │ │ │
│ │ │ │ │ │ │
│ │ │ │ │ │ │
│ │ │ │ ┌───────Query───────┐ │ │
│ │ │ │ │ │ │ │
│ ├────────────┼───────────────────────┼─────────────►│ ActionPlayerInput ├───►│ │
│ │ │ │ │ │ │ │
│ │ │ │ └─────────┬─────────┘ │ │
│ │ │ │ │ │ │
│ │ │ ┌────────┴───────┐ │ │ │
│ │ │ │ │ │ │ │
│ │◄───────────┼──────────────┤ Relay state │◄───────────────┼──────────────┤ │
│ │ │ │ │ │ │ │
│ │ │ └────────┬───────┘ │ │ │
│ │ │ │ │ │ │
│ │ ┌────────┴────────┐ │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ Result Returned │◄─────────────┼────────────────────────┼──────────────┤ │
│ │ │ │ ▼ ▼ │ │
│ │ └────────┬────────┘ │ │
│ │ │ │ │
│ │ │ │ │
└───────────────┘ ▼ └───────────────┘
Name | Type | Byte | Description |
---|---|---|---|
QueryID | uint32_t | 4 | Query ID |
Name | Type | Byte | Description |
---|---|---|---|
QueryID | uint32_t | 4 | Query ID you sent |
struct CreateSession_Param
{
uint32_t QueryID = 101;
uint32_t FieldWidth = 800;
uint32_t FieldHeight = 400;
uint32_t WinScore = 10;
uint32_t GameTime = 300;
float BallSpeed = 1.0f;
float PaddleSpeed = 1.0f;
uint16_t UdpPort_Recv_Stream = 9981;
} param;
send(socket, ¶m, sizeof(param), 0);
struct __attribute__((packed)) CreateSession_Response
{
uint32_t QueryID;
uint8_t Result;
//< There should never exist padding bytes between fields
uint32_t SessionID;
} response;
recv(socket, &response, sizeof(response), 0);
if (response.QueryID == 101)
{
if (response.Result == 0)
{
// Success
std::cout << "SessionID: " << response.SessionID << std::endl;
}
else
{
// Fail
}
}
Request to create a new game session.
-
101
-
Name Type Byte Description FieldWidth uint32_t 4 The width of the field. FieldHeight uint32_t 4 The height of the field WinScore uint32_t 4 The point at which the game ends with a win if reached GameTime uint32_t 4 The time at which the game ends with a win if reached(sec) BallSpeed uint32_t 4 The speed of the ball. (Move distance per second) BallRadius uint32_t 4 The radius of the ball. PaddleSpeed uint32_t 4 The speed of the paddle. PaddleSize uint32_t 4 The size of the paddle. PaddleOffsetFromWall uint32_t 4 The distance between the paddle and the wall. RecvUdpPort_ObjectPos_Stream uint16_t 2 The port number to receive for the position of all objects.
Start sending after calling BeginRound query. (See BeginRound_v1) -
Name Type Byte Description Result uint8_t 1 The result of the request
- 0: Success
- 1: Fail- If Result == success
Name Type Byte Description SessionID uint32_t 4 Unique session ID
- If Result == success
Start a new round.
-
201
-
Name Type Byte Description SessionID uint32_t 4 Unique session ID -
Name Type Byte Description Result uint8_t 1 The result of the request
- 0: Success
- 1: Fail- If Result == success
This response is returned after the round is over.Name Type Byte Description WinPlayer uint32_t 4 The player who won the game
- 0: Draw (Timeover)
- 1: Player A
- 2: Player B
- If Result == success
-
Start sending immediately after a successful BeginRound_v1.
Name Type Byte Description BallPos float[2] 8 The position of the ball PlayerA_PaddlePos float 4 The position of the paddle of player A PlayerB_PaddlePos float 4 The position of the paddle of player B -
Field & Ball Coordinate
PlayerA PlayerB FieldHeight ▲ ┌──────────────┬──────────────┐ │ │ │ │ │ │ │ │ │ │ │ │ ┌─┐ │ │ │ │ │ │ └─┘ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ 0 │ └──────────────┴──────────────┘ ──────────────────────────────► 0 FieldWidth
-
Relative Paddle Coordinate
┌───────────────────┐ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ┌───────┐ │ │ └───────┘ ◄──┼───── Paddle │ │ └───────────────────┘ ──────────|────────► -FieldHeight/2 0 +FieldHeight/2
-
Send the input of the player.
-
301
-
Name Type Byte Description SessionID uint32_t 4 Unique session ID PlayerID uint32_t 4 The ID of the player who sends the input
- 1: Player A
- 2: Player BInputKey uint8_t 1 The input key of the player
- 0: None
- 1: Left
- 2: RightInputType uint8_t 1 The input type of the player
- 0: None
- 1: Press
- 2: Release - No response
Abort a specific session.
-
102
-
Name Type Byte Description SessionID uint32_t 4 Unique session ID -
Name Type Byte Description Result uint8_t 1 The result of the request
- 0: Success
- 1: Fail