Difference between revisions of "Server.c"

From Organic Design wiki
(This should use new linked-list functions too)
(structure and notes)
Line 26: Line 26:
 
// struct type to represent a currently connected stream
 
// struct type to represent a currently connected stream
 
typedef struct streamstruct {
 
typedef struct streamstruct {
char* buf;
 
 
int fd;
 
int fd;
 +
char* in;
 +
char* out;
 
} streamInfo;
 
} streamInfo;
  
Line 71: Line 72:
  
 
// - server is in is in nodal ROOT loop
 
// - server is in is in nodal ROOT loop
void network(node stream) {
+
void network() {
  
int i, stream, nStreams = 0;
+
// NOTE: no need for si struct, just use individual States in streamNode-assocs
  
 +
int i;
 +
streamInfo *si = nodeGetState(this);
 
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;
Line 81: Line 84:
 
FD_ZERO(fdset);
 
FD_ZERO(fdset);
 
FD_SET(server,fdset);
 
FD_SET(server,fdset);
if (select(maxfd+1, fdset, NULL, NULL, &timeout)>0) {
+
if (select(maxfd+1,fdset,NULL,NULL,&timeout)>0) {
 
// new connection
 
// new connection
 +
// - create new stream node and insert into loop
 +
// - create new si struct and SetState of new node
 
}
 
}
  
 
// Data to receive?
 
// Data to receive?
 
FD_ZERO(fdset);
 
FD_ZERO(fdset);
i = 0;
+
FD_SET(si.fd,fdset);
while(si = streams[i++]) FD_SET(si.fd,fdset);
+
if ((i=select(maxfd+1, streams, NULL, NULL, &timeout))>0) {
if (select(maxfd+1, streams, NULL, NULL, &timeout)>0) {
+
// read a packet into si.in
// read packet from each in fdset
+
// 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?
 
// Data to send?
 
FD_ZERO(fdset);
 
FD_ZERO(fdset);
i = 0;
+
FD_SET(si.fd,fdset);
while(si = streams[i++]) FD_SET(si.fd,fdset);
 
 
if (select(maxfd+1, NULL, streams, NULL, &timeout)>0) {
 
if (select(maxfd+1, NULL, streams, NULL, &timeout)>0) {
// write packet from each in fdset
+
// write a packet from si.out
}
 
 
 
 
 
 
 
 
 
 
 
// ****** old loop ******
 
 
 
// 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);
 
  
 
}
 
}
Line 147: Line 118:
  
 
// send response
 
// send response
 +
// - NOTE: this should put the msg in si.out
 
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");
 
}
 
}

Revision as of 11:40, 17 July 2006

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

// Set up socket and listening loop

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

  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);

// struct type to represent a currently connected stream typedef struct streamstruct { int fd; char* in; char* out; } 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, MAXCLIENTS) < 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 // - 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); fcntl(server, O_NONBLOCK);

// Setup stuff for select() struct timeval timeout; fd_set *fdset;

// NOTE: CHANGE THIS TO USE NEW LINKED-LIST FUNCTIONS // array of current client connections // - this may be replaced by blocks pointed to by select()'s fd array streamInfo streams[MAXCLIENTS],si;


// - server is in is in nodal ROOT loop void network() {

// NOTE: no need for si struct, just use individual States in streamNode-assocs

int i; streamInfo *si = nodeGetState(this); 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(maxfd+1,fdset,NULL,NULL,&timeout)>0) { // new connection // - create new stream node and insert into loop // - create new si struct and SetState of new node }

// Data to receive? FD_ZERO(fdset); FD_SET(si.fd,fdset); if ((i=select(maxfd+1, streams, NULL, NULL, &timeout))>0) { // read a packet into si.in // 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(si.fd,fdset); if (select(maxfd+1, NULL, streams, NULL, &timeout)>0) { // write a packet from si.out }

}

// 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"); }