Example Servers Pt 2 Objective: To discuss key aspects of various server implementations
Server Example Outline n Multi-Protocol Server –(Daytimed.cpp) n Multi-Service Server –(Superd.c)
3 Multiprotocol Server daytimed.c /* daytimed.cpp - main, daytime */ #include voiddaytime(char buf[]); voiderrexit(const char *,...); SOCKET passiveTCP(const char *, int); SOCKET passiveUDP(const char *); #define WSVERSMAKEWORD(2, 0) #defineQLEN 5 #defineLINELEN 128
4 Multiprotocol Server daytimed.c void main(int argc, char *argv[]) { char*service = "daytime";// service name charbuf[LINELEN+1];// line buffer structsockaddr_in fsin;// Request from address intalen;// from-address length SOCKETtsock; // TCP master socket SOCKETusock;// UDP socket fd_setrfds;// readable file descriptors intrv;WSADATAwsadata;
5 Multiprotocol Server daytimed.c switch (argc) { case1:break; case2:service = argv[1]; break; default: errexit("usage: daytimed [port]\n"); } if (WSAStartup(WSVERS, &wsadata) != 0) errexit("WSAStartup failed\n"); tsock = passiveTCP(service, QLEN); usock = passiveUDP(service); FD_ZERO(&rfds);
6 Multiprotocol Server daytimed.c while (1) { FD_SET(tsock, &rfds); FD_SET(usock, &rfds); if(select(FD_SETSIZE,&rfds,(fd_set*)0,(fd_set*)0, (struct timeval *)0) == SOCKET_ERROR) errexit("select error: %d\n", GetLastError()); if (FD_ISSET(tsock, &rfds)) { SOCKETssock;/* TCP slave socket*/ alen = sizeof(fsin); ssock = accept(tsock, (struct sockaddr *)&fsin, &alen); if (ssock == INVALID_SOCKET) errexit("accept failed: %d\n",GetLastError());
7 Multiprotocol Server daytimed.c daytime(buf); (void) send(ssock, buf, strlen(buf), 0); (void) closesocket(ssock); } if (FD_ISSET(usock, &rfds)) { alen = sizeof(fsin); rv = recvfrom(usock, buf, sizeof(buf), 0, (struct sockaddr *)&fsin, &alen); if (rv == SOCKET_ERROR) errexit("recvfrom: error %d\n",GetLastError()); daytime(buf); (void) sendto(usock, buf, strlen(buf), 0, (struct sockaddr *)&fsin, sizeof(fsin)); }
8 Multiprotocol Server daytimed.c /* * daytime - fill the given buffer with the time of day * */ void daytime(char buf[]) { time_tnow; (void) time(&now); sprintf(buf, "%s", ctime(&now)); }
9 Multi-service Server - superd.c /* superd.cpp - main, doTCP */ #include #defineUDP_SERV0 #defineTCP_SERV1 struct service { char*sv_name; char sv_useTCP; SOCKET sv_sock; void(*sv_func)(SOCKET); }; voidTCPechod(SOCKET), TCPchargend(SOCKET), TCPdaytimed(SOCKET),TCPtimed(SOCKET);
10 Multi-service Server - superd.c SOCKETpassiveTCP(const char *, int); SOCKETpassiveUDP(const char *); voiderrexit(const char *,...); voiddoTCP(struct service *); struct service svent[] ={ { "echo", TCP_SERV, INVALID_SOCKET, TCPechod }, { "chargen", TCP_SERV, INVALID_SOCKET, TCPchargend }, { "daytime", TCP_SERV, INVALID_SOCKET, TCPdaytimed }, { "time", TCP_SERV, INVALID_SOCKET, TCPtimed }, { 0, 0, 0, 0 }, }; #define WSVERSMAKEWORD(2, 0) #defineQLEN 5 #defineLINELEN 128 externu_shortportbase;/* from passivesock()*/
11 Multi-service Server - superd.c void main(int argc, char *argv[]) { struct service*psv;// service table pointer fd_setafds, rfds;/* file descriptors WSADATAwsdata; switch (argc) { case 1:break; case 2:portbase = (u_short) atoi(argv[1]); break; default:errexit("usage: superd [portbase]\n"); } if (WSAStartup(WSVERS, &wsdata)) errexit("WSAStartup failed\n"); FD_ZERO(&afds);
12 Multi-service Server - superd.c for (psv = &svent[0];psv->sv_name; ++psv) { if (psv->sv_useTCP) psv->sv_sock = passiveTCP(psv->sv_name, QLEN); else psv->sv_sock = passiveUDP(psv->sv_name); FD_SET(psv->sv_sock, &afds); }
Multi-service Server - superd.c while (1) { memcpy(&rfds, &afds, sizeof(rfds)); if (select(FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0,(struct timeval *)0) == SOCKET_ERROR) errexit("select error: %d\n", GetLastError()); for (psv=&svent[0]; psv->sv_name; ++psv) { if (FD_ISSET(psv->sv_sock, &rfds)) { if (psv->sv_useTCP) doTCP(psv); else psv->sv_func(psv->sv_sock); }
14 Multi-service Server superd.c /* * doTCP - handle a TCP service connection request * */ void doTCP(struct service *psv){ struct sockaddr_in fsin;// Request from address intalen;/* from-address length*/ SOCKETssock; alen = sizeof(fsin); ssock = accept(psv->sv_sock,(struct sockaddr*)&fsin,&alen); if (ssock == INVALID_SOCKET) errexit("accept: %d\n", GetLastError()); if (_beginthread((void (*)(void *))psv->sv_func, 0, (void *)ssock) == (unsigned long) -1) errexit("_beginthread: %s\n", strerror(errno)); }
Summary n Servers can use different concurrency techniques to support multiple services at the same time. n Multiprotocol servers support a single server, but through multiple protocols n Multiservice servers share a common infrastructure (process context, etc.) across a number of small, low utilization servers to improve the efficiency of service support.