Difference between revisions of "Server.c"
m |
(add accept() in new connection) |
||
| Line 23: | Line 23: | ||
int processMessage(char* msg); | int processMessage(char* msg); | ||
| + | void noblock(int socket); | ||
// set up socket struct | // set up socket struct | ||
| Line 45: | Line 46: | ||
// start listening for incoming connections | // start listening for incoming connections | ||
if (listen(server, MAXCLIENTS) < 0) logAdd("listen() failed!"; | if (listen(server, MAXCLIENTS) < 0) logAdd("listen() failed!"; | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
// Setup stuff for select() | // Setup stuff for select() | ||
struct timeval timeout; | struct timeval timeout; | ||
fd_set *fdset; | fd_set *fdset; | ||
| + | noblock(server); | ||
// Server is in nodal ROOT loop | // Server is in nodal ROOT loop | ||
| Line 75: | Line 70: | ||
// new connection | // new connection | ||
// - create new stream node and insert into loop | // - create new stream node and insert into loop | ||
| − | // - create new | + | int newstream = accept(server,NULL,NULL); |
| + | noblock(newstream); | ||
| + | // - create new node and its SetState | ||
| + | nodeSetState(newNode,STREAM,&newstream); | ||
*nodeSetState(newNode,INBUF,malloc(BUFSIZE)) = '\0'; | *nodeSetState(newNode,INBUF,malloc(BUFSIZE)) = '\0'; | ||
*nodeSetState(newNode,OUTBUF,malloc(BUFSIZE)) = '\0'; | *nodeSetState(newNode,OUTBUF,malloc(BUFSIZE)) = '\0'; | ||
| Line 111: | Line 109: | ||
if (send(stream, MSG, strlen(MSG)+1, 0) == -1) logAdd("send() failed!"); | if (send(stream, MSG, strlen(MSG)+1, 0) == -1) logAdd("send() failed!"); | ||
else logAdd("Sent message"); | else logAdd("Sent message"); | ||
| + | } | ||
| + | |||
| + | // 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 | ||
| + | // - this may need to be done for each new incomming stream...? | ||
| + | // - some examples use fcntl(server, F_SETFL, FNDELAY) or fcntl(server, F_SETFL, O_NONBLOCK); | ||
| + | void noblock(int socket) { | ||
| + | int opts = fcntl(server, F_GETFL); | ||
| + | if (opts<0) logAdd("noblock() failed!"); | ||
| + | opts = (opts|O_NONBLOCK); | ||
| + | if (fnctl(socket,F_SETFL,opts)<0) logAdd("noblock() failed!"); | ||
} | } | ||
Revision as of 01:44, 18 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 PAKSIZE 128 // keep packet-size small for non-multithreaded design
- define BUFSIZE 10000 // dictates max message size
- define MAXCLIENTS 1000
// - 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 <sys/select.h>
- include <netinet/in.h>
- include <fcntl.h> // needed for O_NONBLOCK option on server
- include <sys/time.h> // for select()
//#include <arpa/inet.h> //#include <netdb.h>
- endif
int processMessage(char* msg); void noblock(int socket);
// 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, MAXCLIENTS) < 0) logAdd("listen() failed!";
// Setup stuff for select() struct timeval timeout; fd_set *fdset; noblock(server);
// Server is in nodal ROOT loop void network() {
// NOTE: no need for si struct, just use individual States in streamNode-assocs
int i; int stream = *nodeGetState(this,STREAM); char *inbuf = nodeGetState(this,INBUF); char *outbuf = nodeGetState(this,OUTBUF); timeout.tv_sec = 1; // later use 0 for min time timeout.tv_usec = 0;
// Check for new connection FD_ZERO(fdset); FD_SET(server,fdset); if (select(server+1,fdset,NULL,NULL,&timeout)>0) { // new connection // - create new stream node and insert into loop int newstream = accept(server,NULL,NULL); noblock(newstream); // - create new node and its SetState nodeSetState(newNode,STREAM,&newstream); *nodeSetState(newNode,INBUF,malloc(BUFSIZE)) = '\0'; *nodeSetState(newNode,OUTBUF,malloc(BUFSIZE)) = '\0'; }
// Data to receive? FD_ZERO(fdset); FD_SET(stream,fdset); if ((i=select(stream+1, fdset, NULL, NULL, &timeout))>0) { // read a packet into inbuf // hook a process into the loop if a msg complete } else if (i<0) { // close connection // - remove this stream node from loop // - free the si struct }
// Data to send?
FD_ZERO(fdset);
FD_SET(stream,fdset);
if (select(stream+1, NULL, fdset, NULL, &timeout)>0) {
// write a packet from outbuf
}
}
// Parses a message content and responds to client int processMessage(char* msg) { // test if restart cmd first
// send response // - NOTE: this should put the msg in si.out if (send(stream, MSG, strlen(MSG)+1, 0) == -1) logAdd("send() failed!"); else logAdd("Sent message"); }
// 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 // - this may need to be done for each new incomming stream...? // - some examples use fcntl(server, F_SETFL, FNDELAY) or fcntl(server, F_SETFL, O_NONBLOCK); void noblock(int socket) { int opts = fcntl(server, F_GETFL); if (opts<0) logAdd("noblock() failed!"); opts = (opts|O_NONBLOCK); if (fnctl(socket,F_SETFL,opts)<0) logAdd("noblock() failed!"); }



