Add comment in void statement
[eleutheria.git] / kqueue / kqclient.c
blob89bcbc420ec95ed9df632bb3abbb3ecd6cb9edf3
1 /*
2 * Compile with:
3 * gcc kqclient.c -o kqclient -Wall -W -Wextra -ansi -pedantic
5 * We will implement a raw tcp client using the kqueue framework.
6 * Whenever the host sends data to the socket, we will print them
7 * in the standard output stream. Similarly, when the user types
8 * something in the standard input stream, we will send it to the
9 * host through the socket.
10 * Basically, we need to monitor the following:
12 * 1. any incoming host data in the socket
13 * 2. any user data in the standard input stream
16 #include <netinet/in.h>
17 #include <sys/event.h>
18 #include <sys/socket.h>
19 #include <sys/time.h>
20 #include <netdb.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
26 #define BUFSIZE 1024
28 /* Function prototypes */
29 void diep(const char *s);
30 int tcpopen(const char *host, int port);
31 void sendbuftosck(int sckfd, const char *buf, int len);
33 int main(int argc, char *argv[])
35 struct kevent chlist[2]; /* events we want to monitor */
36 struct kevent evlist[2]; /* events that were triggered */
37 char buf[BUFSIZE];
38 int sckfd, kq, nev, i;
40 /* Check argument count */
41 if (argc != 3) {
42 fprintf(stderr, "Usage: %s host port\n", argv[0]);
43 exit(EXIT_FAILURE);
46 /* Open a connection to a host:port pair */
47 sckfd = tcpopen(argv[1], atoi(argv[2]));
49 /* Create a new kernel event queue */
50 if ((kq = kqueue()) == -1)
51 diep("kqueue()");
53 /* Initialise kevent structures */
54 EV_SET(&chlist[0], sckfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
55 EV_SET(&chlist[1], fileno(stdin), EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
57 /* Loop forever */
58 for (;;) {
59 nev = kevent(kq, chlist, 2, evlist, 2, NULL);
61 if (nev < 0)
62 diep("kevent()");
64 else if (nev > 0) {
65 if (evlist[0].flags & EV_EOF) /* read direction of socket has shutdown */
66 exit(EXIT_FAILURE);
68 for (i = 0; i < nev; i++) {
69 if (evlist[i].flags & EV_ERROR) { /* report errors */
70 fprintf(stderr, "EV_ERROR: %s\n", strerror(evlist[i].data));
71 exit(EXIT_FAILURE);
74 if (evlist[i].ident == sckfd) { /* we have data from the host */
75 memset(buf, 0, BUFSIZE);
76 if (read(sckfd, buf, BUFSIZE) < 0)
77 diep("read()");
78 fputs(buf, stdout);
81 else if (evlist[i].ident == fileno(stdin)) { /* we have data from stdin */
82 memset(buf, 0, BUFSIZE);
83 fgets(buf, BUFSIZE, stdin);
84 sendbuftosck(sckfd, buf, strlen(buf));
90 /* Close kqueue */
91 if (close(kq) == -1)
92 diep("close()");
94 return EXIT_SUCCESS;
97 void diep(const char *s)
99 perror(s);
100 exit(EXIT_FAILURE);
103 int tcpopen(const char *host, int port)
105 struct sockaddr_in server;
106 struct hostent *hp;
107 int sckfd;
109 if ((hp = gethostbyname(host)) == NULL)
110 diep("gethostbyname()");
112 if ((sckfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
113 diep("socket()");
115 server.sin_family = AF_INET;
116 server.sin_port = htons(port);
117 server.sin_addr = *((struct in_addr *)hp->h_addr);
118 memset(&(server.sin_zero), 0, 8);
120 if (connect(sckfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) < 0)
121 diep("connect()");
123 return sckfd;
126 void sendbuftosck(int sckfd, const char *buf, int len)
128 int bytessent, pos;
130 pos = 0;
131 do {
132 if ((bytessent = send(sckfd, buf + pos, len - pos, 0)) < 0)
133 diep("send()");
134 pos += bytessent;
135 } while (bytessent > 0);