/** Test client for the distributed mutual exclusion algorithm * @author Marko Mäkelä (Marko.Makela@HUT.FI) */ #include #include #include #include #include #include #include #include #ifndef MSG_NOSIGNAL # define MSG_NOSIGNAL 0 #endif /** Messages originated by the client */ enum client_msg { res_req, rel_req }; /** Messages originated by the server */ enum server_msg { res_rej, res_ack, rel_ack }; int main (int argc, char** argv) { /** the datagram socket */ int s; /** the address of the server */ static struct sockaddr_in addr; /** file descriptor set for select(2) */ static fd_set fds; /** timeout for select(2) */ static struct timeval tv; if (argc != 3) { fputs ("usage: client serveraddress portnumber\n", stderr); return 1; } else { const struct hostent* h; char* endp; unsigned long port = strtoul (argv[2], &endp, 0); if (!argv[2] || *endp || port > 65535) { fputs ("invalid remote port number \"", stderr); fputs (argv[2], stderr); fputs ("\"\n", stderr); return 1; } if (!(h = gethostbyname (argv[1]))) { fputs ("gethostbyname: ", stderr); fputs (argv[1], stderr); fputs (": ", stderr); switch (h_errno) { case HOST_NOT_FOUND: fputs ("host not found\n", stderr); break; case NO_ADDRESS: fputs ("no address\n", stderr); break; case NO_RECOVERY: fputs ("non-recoverable error\n", stderr); break; case TRY_AGAIN: fputs ("try again later\n", stderr); break; default: fprintf (stderr, "unknown error %d\n", h_errno); break; } return 2; } if (h->h_addrtype != AF_INET || h->h_length != sizeof addr.sin_addr) { fputs ("gethostbyname ", stderr); fputs (argv[1], stderr); fputs (": not an IPv4 address\n", stderr); return 2; } else memcpy (&addr.sin_addr, h->h_addr, sizeof addr.sin_addr); s = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (s < 0) { perror ("socket"); return 2; } addr.sin_family = AF_INET; addr.sin_port = htons (port); if (connect (s, (const struct sockaddr*) &addr, sizeof addr)) { perror ("connect"); return 2; } } fputs ("press 1 to send res_req, 2 for rel_req, EOF to quit\n", stderr); for (;;) { int i; char c; i = getchar (); switch (i) { case EOF: return 0; default: fputs ("unknown command '", stderr); fputc (i, stderr); fputs ("'\n", stderr); case '\r': case '\n': continue; case '1': c = res_req; break; case '2': c = rel_req; break; } fputs ("sending...", stderr); fflush (stderr); if (1 != send (s, &c, 1, MSG_NOSIGNAL)) { perror ("\nsend"); return 2; } FD_ZERO (&fds); FD_SET (s, &fds); tv.tv_sec = 1, tv.tv_usec = 0; i = select (s + 1, &fds, 0, 0, &tv); if (i < 0) { perror ("\nselect"); return 2; } else if (i != 1) { fputs ("timeout\n", stderr); continue; } i = recv (s, &c, 1, MSG_TRUNC | MSG_NOSIGNAL); if (i < 0) { perror ("\nrecv"); return 2; } fputs ("acknowledged\n", stderr); if (i != 1) fputs ("unexcepted reply packet\n", stderr); else { switch (c) { default: fputs ("unexpected reply PDU\n", stderr); break; case res_rej: fputs ("got res_rej\n", stderr); break; case res_ack: fputs ("got res_ack\n", stderr); break; case rel_ack: fputs ("got rel_ack\n", stderr); break; } } } }