1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
/*
* Copyright 2016 The Emscripten Authors. All rights reserved.
* Emscripten is available under two separate licenses, the MIT license and the
* University of Illinois/NCSA Open Source License. Both these licenses can be
* found in the LICENSE file.
*/
/*
* Compile with:
*
* gcc -Wall `sdl-config --cflags` sdl2_net_server.c -o sdl2_net_server `sdl-config --libs` -lSDL_net
*
* or
*
* emcc -Wall sdl2_net_server.c -s USE_SDL_NET=2 -s USE_SDL=2 -o sdl2_net_server.js
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#include "SDL_net.h"
#define MAX_SOCKETS 128
#define MAX_CLIENTS MAX_SOCKETS - 1
typedef struct {
TCPsocket clientSocket[MAX_CLIENTS];
SDLNet_SocketSet socketSet;
TCPsocket sd; /* Socket descriptor, Client socket descriptor */
} state_t;
state_t state;
void finish() { // untested
printf("Shutting down...\n");
SDLNet_TCP_Close(state.sd);
for (int loop = 0; loop < MAX_CLIENTS; loop++)
{
if (state.clientSocket[loop] != NULL)
{
SDLNet_TCP_Close(state.clientSocket[loop]);
state.clientSocket[loop] = NULL;
}
}
SDLNet_Quit();
#ifdef __EMSCRIPTEN__
emscripten_force_exit(0);
#else
exit(0);
#endif
}
void main_loop() {
char buffer[512];
IPaddress *remoteIP;
/* Check the sd if there is a pending connection.
* If there is one, accept that, and open a new socket for communicating */
SDLNet_CheckSockets(state.socketSet, 20);
int serverSocketActivity = SDLNet_SocketReady(state.sd);
if (serverSocketActivity)
{
printf("new server socket activity!\n");
TCPsocket csd = SDLNet_TCP_Accept(state.sd);
/* Now we can communicate with the client using csd socket
* sd will remain opened waiting other connections */
/* Get the remote address */
if ((remoteIP = SDLNet_TCP_GetPeerAddress(csd)))
{
/* Print the address, converting in the host format */
printf("Host connected: %x %d\n", SDLNet_Read32(&remoteIP->host), SDLNet_Read16(&remoteIP->port));
} else {
fprintf(stderr, "SDLNet_TCP_GetPeerAddress: %s\n", SDLNet_GetError());
}
for (int loop = 0; loop < MAX_CLIENTS; loop++)
{
if (state.clientSocket[loop] == NULL)
{
state.clientSocket[loop] = csd;
SDLNet_TCP_AddSocket(state.socketSet, state.clientSocket[loop]);
break;
}
}
}
for (int clientNumber = 0; clientNumber < MAX_CLIENTS; clientNumber++)
{
int clientSocketActivity = SDLNet_SocketReady(state.clientSocket[clientNumber]);
if (clientSocketActivity != 0)
{
int recvLen = SDLNet_TCP_Recv(state.clientSocket[clientNumber], buffer, 512);
if (recvLen > 0)
{
assert(buffer[recvLen-1] == '\0');
printf("Client %d says: %s\n", clientNumber, buffer);
if (SDLNet_TCP_Send(state.clientSocket[clientNumber], buffer, recvLen) < recvLen) {
printf("Failed to echo message %s\n", buffer);
} else {
printf("Echoed back %d bytes\n", recvLen);
}
if(strcmp(buffer, "exit") == 0) /* Terminate this connection */
{
printf("Terminate connection\n");
SDLNet_TCP_Close(state.clientSocket[clientNumber]);
state.clientSocket[clientNumber] = NULL;
}
if(strcmp(buffer, "quit") == 0) /* Quit the program */
{
printf("Quit program\n");
finish();
}
} else {
printf("Closing client socket\n");
SDLNet_TCP_Close(state.clientSocket[clientNumber]);
state.clientSocket[clientNumber] = NULL;
}
}
}
}
int main(int argc, char **argv)
{
IPaddress ip;
if (SDLNet_Init() < 0)
{
fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
/* Resolving the host using NULL make network interface to listen */
if (SDLNet_ResolveHost(&ip, INADDR_ANY, SOCKK) < 0)
{
fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
state.socketSet = SDLNet_AllocSocketSet(MAX_SOCKETS);
for (int loop = 0; loop < MAX_CLIENTS; loop++)
{
state.clientSocket[loop] = NULL;
}
/* Open a connection with the IP provided (listen on the host's port) */
if (!(state.sd = SDLNet_TCP_Open(&ip)))
{
fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE);
}
SDLNet_TCP_AddSocket(state.socketSet, state.sd);
/* Wait for a connection, send data and term */
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(main_loop, 60, 0);
#else
while (1) main_loop();
#endif
return EXIT_SUCCESS;
}
|