Difference between revisions of "Server.c"
m |
(actually this is wrong - should use select()) |
||
| Line 8: | Line 8: | ||
#define BUFSIZE 10000 // max message size | #define BUFSIZE 10000 // max message size | ||
#define MAXCLIENTS 100 | #define MAXCLIENTS 100 | ||
| − | |||
// - todo: don't exit on connect errors, keep trying every 10s | // - todo: don't exit on connect errors, keep trying every 10s | ||
| Line 17: | Line 16: | ||
#include <sys/socket.h> | #include <sys/socket.h> | ||
#include <netinet/in.h> | #include <netinet/in.h> | ||
| − | #include <fcntl.h> | + | #include <fcntl.h> // needed for O_NONBLOCK option on server |
//#include <arpa/inet.h> | //#include <arpa/inet.h> | ||
//#include <netdb.h> | //#include <netdb.h> | ||
| Line 41: | Line 40: | ||
// get a socket | // get a socket | ||
int server; | int server; | ||
| − | if ((server = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) | + | if ((server = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) logAdd("socket() failed!"; |
| − | |||
| − | |||
| − | |||
// make it reusable | // make it reusable | ||
int sockopt_on = 1; | int sockopt_on = 1; | ||
| − | if (setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &sockopt_on, sizeof(int)) < 0) | + | if (setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &sockopt_on, sizeof(int)) < 0) logAdd("setsockopt() failed!"; |
| − | |||
| − | |||
| − | |||
// bind our socket to the port | // bind our socket to the port | ||
| − | if (bind(server, (struct sockaddr *)&my_addr, sa_in_size) < 0) | + | if (bind(server, (struct sockaddr *)&my_addr, sa_in_size) < 0) logAdd("bind() failed!"; |
| − | |||
| − | |||
| − | |||
// start listening for incoming connections | // start listening for incoming connections | ||
| − | if (listen(server, BACKLOG) < 0) | + | if (listen(server, BACKLOG) < 0) logAdd("listen() failed!"; |
| − | |||
| − | |||
| − | |||
// make the server non-blocking so accept() returns straight away | // make the server non-blocking so accept() returns straight away | ||
| Line 80: | Line 67: | ||
stream = accept(server, (struct sockaddr *)&client_addr, &sa_in_size) | stream = accept(server, (struct sockaddr *)&client_addr, &sa_in_size) | ||
if (stream == EAGAIN) { | if (stream == EAGAIN) { | ||
| − | // No connection requests | + | // No new connection requests - read any available data from streams |
| + | for (i = 0; i < nStreams; i++) { | ||
| + | char* buf = streams[i].buf; | ||
| + | int stream = streams[i].fileno; | ||
| + | } | ||
} | } | ||
| − | else if (stream | + | else if (stream == ECONNABORTED) { |
| − | + | logAdd("Stream closed by client"); | |
| − | + | close(stream); | |
} | } | ||
| + | else if (stream < 0) logAdd("accept() failed!"; | ||
else { | else { | ||
// New stream, create input buffer etc | // New stream, create input buffer etc | ||
| Line 94: | Line 86: | ||
} | } | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
// log the connecter | // log the connecter | ||
| Line 108: | Line 95: | ||
if (recv(stream, buf, bufsize, 0) == -1) perror("recv"); | if (recv(stream, buf, bufsize, 0) == -1) perror("recv"); | ||
else printf("The client says \"%s\"\n", buf); | else printf("The client says \"%s\"\n", buf); | ||
| − | |||
| − | |||
} | } | ||
Revision as of 04:01, 3 July 2006
// good sock function ref at // http://www.opengroup.org/onlinepubs/009695399/idx/networking.html
// Set up socket and listening loop
- define LISTENPORT 2012
- define BACKLOG 10
- define PAKSIZE 128 // keep packet-size small for non-multithreaded design
- define BUFSIZE 10000 // max message size
- define MAXCLIENTS 100
// - todo: don't exit on connect errors, keep trying every 10s // Includes for socket (trying to use one source cpp for osx,win32,*ux)
- ifdef WINDOWS
- include <winsock.h>
- else
- include <sys/socket.h>
- include <netinet/in.h>
- include <fcntl.h> // needed for O_NONBLOCK option on server
//#include <arpa/inet.h> //#include <netdb.h> //#include <unistd.h>
- endif
int processMessage(char* msg);
// struct type to represent a currently connected stream typedef struct streamstruct { char* buf; int fileno; } streamInfo;
// set up socket struct struct sockaddr_in my_addr, client_addr; int sa_in_size = sizeof(struct sockaddr_in); memset((char *)&my_addr, 0, sa_in_size); // zero the struct my_addr.sin_family = PF_INET; my_addr.sin_port = htons(LISTENPORT); my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
// get a socket int server; if ((server = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) logAdd("socket() failed!";
// make it reusable int sockopt_on = 1; if (setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &sockopt_on, sizeof(int)) < 0) logAdd("setsockopt() failed!";
// bind our socket to the port if (bind(server, (struct sockaddr *)&my_addr, sa_in_size) < 0) logAdd("bind() failed!";
// start listening for incoming connections if (listen(server, BACKLOG) < 0) logAdd("listen() failed!";
// make the server non-blocking so accept() returns straight away // - if no incoming requests, returns EAGAIN or EWOULDBLOCK state // - we need this for non-multithreaded design fcntl(server, O_NONBLOCK);
// array of current client connections streamInfo* streams[MAXCLIENTS];
int i, stream, nStreams = 0; while(1) {
// Wait for any incomming connection // O_NONBLOCK is set so, EAGAIN or EWOULDBLOCK returned if no requests stream = accept(server, (struct sockaddr *)&client_addr, &sa_in_size) if (stream == EAGAIN) { // No new connection requests - read any available data from streams for (i = 0; i < nStreams; i++) { char* buf = streams[i].buf; int stream = streams[i].fileno; } } else if (stream == ECONNABORTED) { logAdd("Stream closed by client"); close(stream); } else if (stream < 0) logAdd("accept() failed!"; else { // New stream, create input buffer etc streamInfo si; si.buf = malloc(BUFSIZE); si.fileno = stream; streams[nStreams++] = &si; }
// log the connecter
// - should get info for this stream, incl buf
printf("got connection from %s\n", inet_ntoa(client_addr.sin_addr));
// get the reply // - should keep receiving until \r\n\0?, then call serverProcessMessage() if (recv(stream, buf, bufsize, 0) == -1) perror("recv"); else printf("The client says \"%s\"\n", buf);
}
// Parses a message content and responds to client int processMessage(char* msg) { // test if restart cmd first
// send response if (send(stream, MSG, strlen(MSG)+1, 0) == -1) { perror("send"); } else printf("Sent message MSG\n"); }



