Difference between revisions of "Server.c"
m |
(split network out to stwo functions - server() and stream()) |
||
| Line 15: | Line 15: | ||
#include <sys/select.h> | #include <sys/select.h> | ||
#include <netinet/in.h> | #include <netinet/in.h> | ||
| − | #include <fcntl.h> // needed for O_NONBLOCK option on | + | #include <fcntl.h> // needed for O_NONBLOCK option on sock |
#include <sys/time.h> // for select() | #include <sys/time.h> // for select() | ||
//#include <arpa/inet.h> | //#include <arpa/inet.h> | ||
| Line 28: | Line 28: | ||
struct timeval timeout; | struct timeval timeout; | ||
fd_set *fdset; | fd_set *fdset; | ||
| − | int | + | int sock, sockopt_on = 1, szAddr = sizeof(struct sockaddr_in); |
memset((char*)&addr, 0, szAddr); // zero the struct | memset((char*)&addr, 0, szAddr); // zero the struct | ||
addr.sin_family = PF_INET; | addr.sin_family = PF_INET; | ||
| Line 35: | Line 35: | ||
// Do the usual socket polava: create,options,bind,listen | // Do the usual socket polava: create,options,bind,listen | ||
| − | if (( | + | if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) logAdd("socket() failed!"); |
| − | if (setsockopt( | + | if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sockopt_on, sizeof(int)) < 0) logAdd("setsockopt() failed!"); |
| − | if (bind(nonblocking( | + | if (bind(nonblocking(sock), (struct sockaddr*)&addr, szAddr) < 0) logAdd("bind() failed!"); |
| − | if (listen( | + | if (listen(sock, MAXCLIENTS) < 0) logAdd("listen() failed!"); |
| − | // | + | // Function called by main network node in root reduction loop |
| − | void | + | void server() { |
| + | // Check for new connection, if so create new stream-node | ||
| + | FD_ZERO(fdset); | ||
| + | FD_SET(sock,fdset); | ||
| + | if (select(sock+1, fdset, NULL, NULL, &timeout)>0) { | ||
| + | int *newstream = malloc(sizeof(int)); | ||
| + | nonblocking(*newstream = accept(sock, NULL, NULL)); | ||
| + | |||
| + | // todo: change this to a single state with ptr-to-struct of these pointers | ||
| + | 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; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Function called by each stream in network's reduction loop | ||
| + | void stream() { | ||
// NOTE: no need for si struct, just use individual States in streamNode-assocs | // NOTE: no need for si struct, just use individual States in streamNode-assocs | ||
| Line 51: | Line 69: | ||
timeout.tv_sec = 1; // later use 0 for min time | timeout.tv_sec = 1; // later use 0 for min time | ||
timeout.tv_usec = 0; | timeout.tv_usec = 0; | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
// Data to receive? | // Data to receive? | ||
| Line 112: | Line 116: | ||
// - if no incoming requests, returns EAGAIN or EWOULDBLOCK state | // - if no incoming requests, returns EAGAIN or EWOULDBLOCK state | ||
int nonblocking(int socket) { | int nonblocking(int socket) { | ||
| − | int opts = fcntl( | + | int opts = fcntl(sock, F_GETFL); |
if (opts<0) logAdd("noblock() failed!"); | if (opts<0) logAdd("noblock() failed!"); | ||
opts = (opts|O_NONBLOCK); | opts = (opts|O_NONBLOCK); | ||
Revision as of 00:26, 19 July 2006
// good sock function ref at // http://www.opengroup.org/onlinepubs/009695399/idx/networking.html
// Set up socket and listening loop
- 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 sock
- include <sys/time.h> // for select()
//#include <arpa/inet.h> //#include <netdb.h>
- 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 sock, 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 ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) logAdd("socket() failed!"); if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sockopt_on, sizeof(int)) < 0) logAdd("setsockopt() failed!"); if (bind(nonblocking(sock), (struct sockaddr*)&addr, szAddr) < 0) logAdd("bind() failed!"); if (listen(sock, MAXCLIENTS) < 0) logAdd("listen() failed!");
// Function called by main network node in root reduction loop void server() { // Check for new connection, if so create new stream-node FD_ZERO(fdset); FD_SET(sock,fdset); if (select(sock+1, fdset, NULL, NULL, &timeout)>0) { int *newstream = malloc(sizeof(int)); nonblocking(*newstream = accept(sock, NULL, NULL));
// todo: change this to a single state with ptr-to-struct of these pointers 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; } }
// Function called by each stream in network's reduction loop void stream() {
// 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;
// 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(sock, F_GETFL); if (opts<0) logAdd("noblock() failed!"); opts = (opts|O_NONBLOCK); if (fnctl(socket,F_SETFL,opts)<0) logAdd("noblock() failed!"); return socket; }



