Difference between revisions of "Server.c"

From Organic Design wiki
m
m
Line 22: Line 22:
  
 
int processMessage(char* msg);
 
int processMessage(char* msg);
void noblock(int socket);
+
int nonblocking(int socket);
  
 
// Set up structures for socket & select
 
// Set up structures for socket & select
Line 111: Line 111:
 
}
 
}
  
// make the server non-blocking so accept() returns straight away
+
// make the passed socket non-blocking so accept() returns straight away for multiplexed model
 
// - if no incoming requests, returns EAGAIN or EWOULDBLOCK state
 
// - 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);
 
 
int nonblocking(int socket) {
 
int nonblocking(int socket) {
 
int opts = fcntl(server, F_GETFL);
 
int opts = fcntl(server, F_GETFL);

Revision as of 10:23, 18 July 2006

// good sock function ref at // http://www.opengroup.org/onlinepubs/009695399/idx/networking.html

// Set up socket and listening loop

  1. define PAKSIZE 128 // keep packet-size small for non-multithreaded design
  2. define BUFSIZE 10000 // dictates max message size
  3. 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)

  1. ifdef WINDOWS
  2. include <winsock.h>
  3. else
  4. include <sys/socket.h>
  5. include <sys/select.h>
  6. include <netinet/in.h>
  7. include <fcntl.h> // needed for O_NONBLOCK option on server
  8. include <sys/time.h> // for select()

//#include <arpa/inet.h> //#include <netdb.h>

  1. endif

int processMessage(char* msg); int nonblocking(int socket);

// Set up structures for socket & select struct sockaddr_in addr; struct timeval timeout; fd_set *fdset; int server, sockopt_on = 1, szAddr = sizeof(struct sockaddr_in); memset((char*)&addr, 0, szAddr); // zero the struct addr.sin_family = PF_INET; addr.sin_port = htons(atoi(*hash("port"))); addr.sin_addr.s_addr = htonl(INADDR_ANY);

// Do the usual socket polava: create,options,bind,listen if ((server = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) logAdd("socket() failed!"); if (setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &sockopt_on, sizeof(int)) < 0) logAdd("setsockopt() failed!"); if (bind(nonblocking(server), (struct sockaddr*)&addr, szAddr) < 0) logAdd("bind() failed!"); if (listen(server, MAXCLIENTS) < 0) logAdd("listen() failed!");

// Declare the nodal server-iteration function 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 int *newstream = malloc(sizeof(int)); nonblocking(*newstream = accept(server, NULL, NULL)); nodeSetState(newNode, STREAM, newstream);

*nodeSetState(newNode, INBUF, malloc(BUFSIZE)) = '\0'; *nodeSetState(newNode, INPTR, malloc(sizeof(int*))) = 0;

*nodeSetState(newNode, OUTBUF, malloc(BUFSIZE)) = '\0'; *nodeSetState(newNode, OUTPTR, malloc(sizeof(int*))) = 0; }

// Data to receive? FD_ZERO(fdset); FD_SET(*stream,fdset); if (select(1+*stream, fdset, NULL, NULL, &timeout)>0) { // read a packet into inbuf if ((i = recv(*stream, inbuf+*inptr, PAKSIZE, 0)>0) { if (complete_message) { *inptr -= msg_size; // hook a process into the loop } } else if (i == 0) { // zero bytes to read, do orderly termination // todo: remove this stream node from loop free(stream); free(inbuf); free(inptr); free(outbuf); free(outptr); } else logErr("recv(): failed!"); }


// Data to send? FD_ZERO(fdset); FD_SET(*stream,fdset); if (select(1+*stream, 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 passed socket non-blocking so accept() returns straight away for multiplexed model // - if no incoming requests, returns EAGAIN or EWOULDBLOCK state int nonblocking(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!"); return socket; }