// the server // compile with CC server.cpp -o server // then, if you want a random port assigned, just say // server // if you want to use e.g. port 21000, just say // server 21000 // see the sample main. A server program should create one // "server" object when it starts. the "wait" method returns // and "event" object. The "who" member of an event is a // pointer to a "client" object describing the user who // caused the event, or NULL if there wasn't one. #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern int errno; string is(int n) { char s[20]; sprintf(s, "%d", n); return s; } const int maxclients = 6; const string timeout = "timeout"; const string connection = "connection"; const string disconnection = "disconnection"; const string rejection = "rejection"; const string input = "input"; const string hiccup = "hiccup"; // the four members string1, string2, int1, int2, are not used at all. // you can use them for anything you want struct client { string ip; int port, fd, sessionid; string string1, string2; int int1, int2; static int sessions; client(string a, int b, int c); void send(string s); void disconnect(); }; int client::sessions=0; client::client(string a, int b, int c) { ip=a; port=b; fd=c; string1=""; string2=""; int1=0; int2=0; sessions+=1; sessionid=sessions; } void client::disconnect() { close(fd); fd=-1; } void client::send(string s) { write(fd, s.c_str(), s.length()); } struct event { string what; client * who; string data; event(string a, client * b, string c) { what=a; who=b; data=c; } }; struct server { int port; string hostname, ip; int main_socket; static bool randomised; client * clients[maxclients]; int numclients; server(int port=0); event wait(double maxtime=2.5); }; bool server::randomised = false; server::server(int p) { for (int i=0; ih_addr); main_socket = socket(AF_INET, SOCK_STREAM, 0); if (main_socket<0) { perror("socket creation"); exit(1); } while (1) { sockaddr_in server_info; server_info.sin_len = sizeof(server_info); server_info.sin_family = AF_INET; server_info.sin_addr.s_addr = htonl(INADDR_ANY); server_info.sin_port = htons(port); int r1 = bind(main_socket, (sockaddr *) &server_info, sizeof(server_info)); if (r1>=0) break; else if (p==0) { port+=1; if (port-firstport>1000) { perror("ports already in use"); exit(1); } } else { perror("ports already in use"); exit(1); } } int r2 = listen(main_socket, 3); if (r2<0) { perror("listen"); exit(1); } printf("Listening on %s, %s, port %d\n", hostname.c_str(), ip.c_str(), port); numclients=0; } event server::wait(double maxtime) { while (1) { fd_set fds; int maxfd=main_socket; FD_ZERO(&fds); FD_SET(main_socket, &fds); for (int i=0; ifd; FD_SET(fd, &fds); if (fd>maxfd) maxfd=fd; } timeval maxwait; maxwait.tv_sec=(int)maxtime; maxwait.tv_usec=(int)((maxtime-(int)maxtime)*1000000); int r3 = select(maxfd+1, &fds, NULL, NULL, &maxwait); if (r3<0) { perror("select"); sleep(2); continue; } else if (r3==0) return event(timeout, 0, timeout); else if (FD_ISSET(main_socket, &fds)) { sockaddr_in client_info; unsigned int client_info_size = sizeof(client_info); int session_socket = accept(main_socket, (sockaddr *) &client_info, &client_info_size); if (session_socket<0) { if (errno==EINTR) continue; // EINTR is not a problem perror("accept"); usleep(100000); return event(hiccup, 0, hiccup); } if (numclients>=maxclients) { close(session_socket); return event(rejection, NULL, "too many clients"); } else { clients[numclients]=new client(inet_ntoa(client_info.sin_addr), ntohs(client_info.sin_port), session_socket); numclients+=1; return event(connection, clients[numclients-1], ""); } } else { for (int i=0; ifd; if (FD_ISSET(fd, &fds)) { char s[1000]; int n=read(fd, s, 999); if (n<=0) { close(fd); client * c = clients[i]; numclients-=1; for (int j=i; j0 && s[n-1]<' ') n-=1; s[n]=0; return event(input, clients[i], s); } } } } } void main(int argc, char *argv[]) { int port_number = 0; if (argc>=2) port_number = atol(argv[1]); server srv(port_number); while (true) { event e = srv.wait(); if (e.what==connection) { cout << "connection\n"; for (int i=0; isend(e.who->ip+":"+is(e.who->port)+" session "+is(e.who->sessionid)+" arrived"); } } else if (e.what==disconnection) { for (int i=0; isend(e.who->ip+":"+is(e.who->port)+" session "+is(e.who->sessionid)+" departed"); } delete e.who; } else if (e.what==timeout) cout << "tick\n"; else if (e.what==input) { cout << "received:\n" << e.data << "\n"; for (int i=0; isend(e.data); } } else if (e.who==NULL) cout << e.what << " '" << e.data << "'\n"; else cout << e.what << " from " << e.who->ip << ":" << e.who->port << " '" << e.data << "'\n"; } }