network_ping_pong.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*******************************************************************************************
  2. *
  3. * raylib [network] example - Client/Server ping-pong
  4. *
  5. * Welcome to raylib!
  6. *
  7. * To test examples, just press F6 and execute raylib_compile_execute script
  8. * Note that compiled executable is placed in the same folder as .c file
  9. *
  10. * You can find all basic examples on C:\raylib\raylib\examples folder or
  11. * raylib official webpage: www.raylib.com
  12. *
  13. * Enjoy using raylib. :)
  14. *
  15. * This example has been created using raylib 2.0 (www.raylib.com)
  16. * raylib is licensed under an unmodified zlib/libpng license (View raylib.h
  17. *for details)
  18. *
  19. * Copyright (c) 2013-2016 Ramon Santamaria (@raysan5)
  20. *
  21. ********************************************************************************************/
  22. #include "raylib.h"
  23. #include "rnet.h"
  24. #include <assert.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. float elapsed = 0.0f;
  28. float delay = 1.0f;
  29. bool ping = false;
  30. bool pong = false;
  31. bool connected = false;
  32. bool client_connected = false;
  33. const char * pingmsg = "Ping!";
  34. const char * pongmsg = "Pong!";
  35. int msglen = 0;
  36. SocketConfig server_cfg = {.host = "127.0.0.1", .port = "4950", .type = SOCKET_TCP, .server = true, .nonblocking = true};
  37. SocketConfig client_cfg = {.host = "127.0.0.1", .port = "4950", .type = SOCKET_TCP, .nonblocking = true};
  38. SocketConfig connection_cfg = {.nonblocking = true};
  39. SocketResult *server_res = NULL;
  40. SocketResult *client_res = NULL;
  41. SocketSet * socket_set = NULL;
  42. Socket * connection = NULL;
  43. char recvBuffer[512];
  44. // Attempt to connect to the network (Either TCP, or UDP)
  45. void NetworkConnect()
  46. {
  47. // If the server is configured as UDP, ignore connection requests
  48. if (server_cfg.type == SOCKET_UDP && client_cfg.type == SOCKET_UDP) {
  49. ping = true;
  50. connected = true;
  51. } else {
  52. // If the client is connected, run the server code to check for a connection
  53. if (client_connected) {
  54. int active = CheckSockets(socket_set, 0);
  55. if (active != 0) {
  56. TraceLog(LOG_DEBUG,
  57. "There are currently %d socket(s) with data to be processed.", active);
  58. }
  59. if (active > 0) {
  60. if ((connection = SocketAccept(server_res->socket, &connection_cfg)) != NULL) {
  61. AddSocket(socket_set, connection);
  62. ping = true;
  63. connected = true;
  64. }
  65. }
  66. } else {
  67. // Check if we're connected every _delay_ seconds
  68. elapsed += GetFrameTime();
  69. if (elapsed > delay) {
  70. if (IsSocketConnected(client_res->socket)) {
  71. client_connected = true;
  72. }
  73. elapsed = 0.0f;
  74. }
  75. }
  76. }
  77. }
  78. // Once connected to the network, check the sockets for pending information
  79. // and when information is ready, send either a Ping or a Pong.
  80. void NetworkUpdate()
  81. {
  82. // CheckSockets
  83. //
  84. // If any of the sockets in the socket_set are pending (received data, or requests)
  85. // then mark the socket as being ready. You can check this with IsSocketReady(client_res->socket)
  86. int active = CheckSockets(socket_set, 0);
  87. if (active != 0) {
  88. TraceLog(LOG_DEBUG,
  89. "There are currently %d socket(s) with data to be processed.", active);
  90. }
  91. // IsSocketReady
  92. //
  93. // If the socket is ready, attempt to receive data from the socket
  94. int bytesRecv = 0;
  95. if (server_cfg.type == SOCKET_UDP && client_cfg.type == SOCKET_UDP) {
  96. if (IsSocketReady(client_res->socket)) {
  97. bytesRecv = SocketReceive(client_res->socket, recvBuffer, msglen);
  98. }
  99. if (IsSocketReady(server_res->socket)) {
  100. bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen);
  101. }
  102. } else {
  103. if (IsSocketReady(connection)) {
  104. bytesRecv = SocketReceive(connection, recvBuffer, msglen);
  105. }
  106. }
  107. // If we received data, was that data a "Ping!" or a "Pong!"
  108. if (bytesRecv > 0) {
  109. if (strcmp(recvBuffer, pingmsg) == 0) { pong = true; }
  110. if (strcmp(recvBuffer, pongmsg) == 0) { ping = true; }
  111. }
  112. // After each delay has expired, send a response "Ping!" for a "Pong!" and vice versa
  113. elapsed += GetFrameTime();
  114. if (elapsed > delay) {
  115. if (ping) {
  116. ping = false;
  117. if (server_cfg.type == SOCKET_UDP && client_cfg.type == SOCKET_UDP) {
  118. SocketSend(client_res->socket, pingmsg, msglen);
  119. } else {
  120. SocketSend(client_res->socket, pingmsg, msglen);
  121. }
  122. } else if (pong) {
  123. pong = false;
  124. if (server_cfg.type == SOCKET_UDP && client_cfg.type == SOCKET_UDP) {
  125. SocketSend(client_res->socket, pongmsg, msglen);
  126. } else {
  127. SocketSend(client_res->socket, pongmsg, msglen);
  128. }
  129. }
  130. elapsed = 0.0f;
  131. }
  132. }
  133. int main()
  134. {
  135. // Setup
  136. int screenWidth = 800;
  137. int screenHeight = 450;
  138. InitWindow(
  139. screenWidth, screenHeight, "raylib [network] example - ping pong");
  140. SetTargetFPS(60);
  141. SetTraceLogLevel(LOG_DEBUG);
  142. // Networking
  143. InitNetwork();
  144. // Create the server
  145. //
  146. // Performs
  147. // getaddrinfo
  148. // socket
  149. // setsockopt
  150. // bind
  151. // listen
  152. server_res = AllocSocketResult();
  153. if (!SocketCreate(&server_cfg, server_res)) {
  154. TraceLog(LOG_WARNING, "Failed to open server: status %d, errno %d",
  155. server_res->status, server_res->socket->status);
  156. } else {
  157. if (!SocketBind(&server_cfg, server_res)) {
  158. TraceLog(LOG_WARNING, "Failed to bind server: status %d, errno %d",
  159. server_res->status, server_res->socket->status);
  160. } else {
  161. if (!(server_cfg.type == SOCKET_UDP)) {
  162. if (!SocketListen(&server_cfg, server_res)) {
  163. TraceLog(LOG_WARNING,
  164. "Failed to start listen server: status %d, errno %d",
  165. server_res->status, server_res->socket->status);
  166. }
  167. }
  168. }
  169. }
  170. // Create the client
  171. //
  172. // Performs
  173. // getaddrinfo
  174. // socket
  175. // setsockopt
  176. // connect (TCP only)
  177. client_res = AllocSocketResult();
  178. if (!SocketCreate(&client_cfg, client_res)) {
  179. TraceLog(LOG_WARNING, "Failed to open client: status %d, errno %d",
  180. client_res->status, client_res->socket->status);
  181. } else {
  182. if (!(client_cfg.type == SOCKET_UDP)) {
  183. if (!SocketConnect(&client_cfg, client_res)) {
  184. TraceLog(LOG_WARNING,
  185. "Failed to connect to server: status %d, errno %d",
  186. client_res->status, client_res->socket->status);
  187. }
  188. }
  189. }
  190. // Create & Add sockets to the socket set
  191. socket_set = AllocSocketSet(3);
  192. msglen = strlen(pingmsg) + 1;
  193. memset(recvBuffer, '\0', sizeof(recvBuffer));
  194. AddSocket(socket_set, server_res->socket);
  195. AddSocket(socket_set, client_res->socket);
  196. // Main game loop
  197. while (!WindowShouldClose()) {
  198. BeginDrawing();
  199. ClearBackground(RAYWHITE);
  200. if (connected) {
  201. NetworkUpdate();
  202. } else {
  203. NetworkConnect();
  204. }
  205. EndDrawing();
  206. }
  207. // Cleanup
  208. CloseWindow();
  209. return 0;
  210. }