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>
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 */
38 int sckfd
, kq
, nev
, i
;
40 /* Check argument count */
42 fprintf(stderr
, "Usage: %s host port\n", argv
[0]);
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)
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);
59 nev
= kevent(kq
, chlist
, 2, evlist
, 2, NULL
);
65 if (evlist
[0].flags
& EV_EOF
)
66 /* Read direction of socket has shutdown */
69 for (i
= 0; i
< nev
; i
++) {
70 if (evlist
[i
].flags
& EV_ERROR
) {
72 fprintf(stderr
, "EV_ERROR: %s\n", strerror(evlist
[i
].data
));
76 if (evlist
[i
].ident
== sckfd
) {
77 /* We have data from the host */
78 memset(buf
, 0, BUFSIZE
);
79 if (read(sckfd
, buf
, BUFSIZE
) < 0)
84 else if (evlist
[i
].ident
== fileno(stdin
)) {
85 /* We have data from stdin */
86 memset(buf
, 0, BUFSIZE
);
87 fgets(buf
, BUFSIZE
, stdin
);
88 sendbuftosck(sckfd
, buf
, strlen(buf
));
101 void diep(const char *s
)
107 int tcpopen(const char *host
, int port
)
109 struct sockaddr_in server
;
113 if ((hp
= gethostbyname(host
)) == NULL
)
114 diep("gethostbyname()");
116 if ((sckfd
= socket(PF_INET
, SOCK_STREAM
, 0)) < 0)
119 server
.sin_family
= AF_INET
;
120 server
.sin_port
= htons(port
);
121 server
.sin_addr
= *((struct in_addr
*)hp
->h_addr
);
122 memset(&(server
.sin_zero
), 0, 8);
124 if (connect(sckfd
, (struct sockaddr
*)&server
, sizeof(struct sockaddr
)) < 0)
130 void sendbuftosck(int sckfd
, const char *buf
, int len
)
136 if ((bytessent
= send(sckfd
, buf
+ pos
, len
- pos
, 0)) < 0)
139 } while (bytessent
> 0);