1 /*******************************************************************************************
2 *
3 * raylib [network] example - Client/Server ping-pong
4 *
5 * This example has been created using raylib 3.0 (www.raylib.com)
6 * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
7 *
8 * Copyright (c) 2019-2020 Jak Barnes (@syphonx) and Ramon Santamaria (@raysan5)
9 *
10 ********************************************************************************************/
11
12 #include "raylib.h"
13
14 #define RNET_IMPLEMENTATION
15 #include "rnet.h"
16
17 float elapsed = 0.0f;
18 float delay = 1.0f;
19 bool ping = false;
20 bool pong = false;
21 bool connected = false;
22 bool clientConnected = false;
23 const char *pingmsg = "Ping!";
24 const char *pongmsg = "Pong!";
25 int msglen = 0;
26 SocketConfig serverConfig = { .host = "127.0.0.1", .port = "4950", .type = SOCKET_TCP, .server = true, .nonblocking = true };
27 SocketConfig clientConfig = { .host = "127.0.0.1", .port = "4950", .type = SOCKET_TCP, .nonblocking = true };
28 SocketConfig connectionConfig = { .nonblocking = true };
29 SocketResult *serverResult = NULL;
30 SocketResult *clientResult = NULL;
31 SocketSet *socketSet = NULL;
32 Socket *connection = NULL;
33 char receiveBuffer[512] = { 0 };
34
35 // Attempt to connect to the network (Either TCP, or UDP)
NetworkConnect(void)36 static void NetworkConnect(void)
37 {
38 // If the server is configured as UDP, ignore connection requests
39 if ((serverConfig.type == SOCKET_UDP) && (clientConfig.type == SOCKET_UDP))
40 {
41 ping = true;
42 connected = true;
43 }
44 else
45 {
46 // If the client is connected, run the server code to check for a connection
47 if (clientConnected)
48 {
49 int active = CheckSockets(socketSet, 0);
50 if (active != 0) TraceLog(LOG_INFO, "There are currently %d socket(s) with data to be processed.", active);
51
52 if (active > 0)
53 {
54 if ((connection = SocketAccept(serverResult->socket, &connectionConfig)) != NULL)
55 {
56 AddSocket(socketSet, connection);
57 connected = true;
58 ping = true;
59 }
60 }
61 }
62 else
63 {
64 // Check if we're connected every _delay_ seconds
65 elapsed += GetFrameTime();
66 if (elapsed > delay)
67 {
68 if (IsSocketConnected(clientResult->socket)) clientConnected = true;
69
70 elapsed = 0.0f;
71 }
72 }
73 }
74 }
75
76 // Once connected to the network, check the sockets for pending information
77 // and when information is ready, send either a Ping or a Pong.
UpdateNetwork(void)78 static void UpdateNetwork(void)
79 {
80 // CheckSockets, if any of the sockets in the socketSet are pending (received data, or requests)
81 // then mark the socket as being ready. You can check this with IsSocketReady(clientResult->socket)
82 int active = CheckSockets(socketSet, 0);
83 if (active != 0) TraceLog(LOG_DEBUG, "There are currently %d socket(s) with data to be processed.", active);
84
85 // IsSocketReady, if the socket is ready, attempt to receive data from the socket
86 int bytesRecv = 0;
87 if ((serverConfig.type == SOCKET_UDP) && (clientConfig.type == SOCKET_UDP))
88 {
89 if (IsSocketReady(clientResult->socket)) bytesRecv = SocketReceive(clientResult->socket, receiveBuffer, msglen);
90 if (IsSocketReady(serverResult->socket)) bytesRecv = SocketReceive(serverResult->socket, receiveBuffer, msglen);
91 }
92 else if (IsSocketReady(connection)) bytesRecv = SocketReceive(connection, receiveBuffer, msglen);
93
94 // If we received data, was that data a "Ping!" or a "Pong!"
95 if (bytesRecv > 0)
96 {
97 if (strcmp(receiveBuffer, pingmsg) == 0) { pong = true; }
98 if (strcmp(receiveBuffer, pongmsg) == 0) { ping = true; }
99 }
100
101 // After each delay has expired, send a response "Ping!" for a "Pong!" and vice versa
102 elapsed += GetFrameTime();
103 if (elapsed > delay)
104 {
105 if (ping)
106 {
107 ping = false;
108 if (serverConfig.type == SOCKET_UDP && clientConfig.type == SOCKET_UDP) SocketSend(clientResult->socket, pingmsg, msglen);
109 else SocketSend(clientResult->socket, pingmsg, msglen);
110 }
111 else if (pong)
112 {
113 pong = false;
114 if (serverConfig.type == SOCKET_UDP && clientConfig.type == SOCKET_UDP) SocketSend(clientResult->socket, pongmsg, msglen);
115 else SocketSend(clientResult->socket, pongmsg, msglen);
116 }
117
118 elapsed = 0.0f;
119 }
120 }
121
main(void)122 int main(void)
123 {
124 // Initialization
125 //--------------------------------------------------------------------------------------
126 const int screenWidth = 800;
127 const int screenHeight = 450;
128
129 InitWindow(screenWidth, screenHeight, "raylib [network] example - ping pong");
130
131 InitNetworkDevice(); // Init network communications
132
133 // Create the server: getaddrinfo + socket + setsockopt + bind + listen
134 serverResult = LoadSocketResult();
135 if (!SocketCreate(&serverConfig, serverResult))
136 {
137 TraceLog(LOG_WARNING, "Failed to open server: status %d, errno %d", serverResult->status, serverResult->socket->status);
138 }
139 else
140 {
141 if (!SocketBind(&serverConfig, serverResult))
142 {
143 TraceLog(LOG_WARNING, "Failed to bind server: status %d, errno %d", serverResult->status, serverResult->socket->status);
144 }
145 else
146 {
147 if (!(serverConfig.type == SOCKET_UDP))
148 {
149 if (!SocketListen(&serverConfig, serverResult))
150 {
151 TraceLog(LOG_WARNING, "Failed to start listen server: status %d, errno %d", serverResult->status, serverResult->socket->status);
152 }
153 }
154 }
155 }
156
157 // Create the client: getaddrinfo + socket + setsockopt + connect (TCP only)
158 clientResult = LoadSocketResult();
159 if (!SocketCreate(&clientConfig, clientResult))
160 {
161 TraceLog(LOG_WARNING, "Failed to open client: status %d, errno %d", clientResult->status, clientResult->socket->status);
162 }
163 else
164 {
165 if (!(clientConfig.type == SOCKET_UDP))
166 {
167 if (!SocketConnect(&clientConfig, clientResult))
168 {
169 TraceLog(LOG_WARNING, "Failed to connect to server: status %d, errno %d", clientResult->status, clientResult->socket->status);
170 }
171 }
172 }
173
174 // Create and add sockets to the socket set
175 socketSet = LoadSocketSet(3);
176
177 AddSocket(socketSet, serverResult->socket);
178 AddSocket(socketSet, clientResult->socket);
179
180 SetTargetFPS(60); // Set our game to run at 60 frames-per-second
181 //--------------------------------------------------------------------------------------
182
183 // Main game loop
184 while (!WindowShouldClose()) // Detect window close button or ESC key
185 {
186 // Update
187 //----------------------------------------------------------------------------------
188 if (connected) UpdateNetwork();
189 //else NetworkConnect();
190 //----------------------------------------------------------------------------------
191
192 // Draw
193 //----------------------------------------------------------------------------------
194 BeginDrawing();
195
196 ClearBackground(RAYWHITE);
197
198 // TODO: Draw relevant connection info
199
200 EndDrawing();
201 //----------------------------------------------------------------------------------
202 }
203
204 // De-Initialization
205 //--------------------------------------------------------------------------------------
206 CloseNetworkDevice(); // Close network communication
207
208 CloseWindow(); // Close window and OpenGL context
209 //--------------------------------------------------------------------------------------
210
211 return 0;
212 }