2 gcc kqclient.c -o kqclient -Wall -W -Wextra -ansi -pedantic
4 We will implement a raw tcp client using the kqueue framework.
5 Whenever the host sends data to the socket, we will print them
6 in the standard output stream. Similarly, when the user types
7 something in the standard input stream, we will send it to the
8 host through the socket.
9 Basically, we need to monitor the following:
11 1. any incoming host data in the socket
12 2. any user data in the standard input stream
15 #include <netinet/in.h>
16 #include <sys/event.h>
17 #include <sys/socket.h>
27 /* function prototypes */
28 void diep(const char *s
);
29 int tcpopen(const char *host
, int port
);
30 void sendbuftosck(int sckfd
, const char *buf
, int len
);
32 int main(int argc
, char *argv
[])
34 struct kevent chlist
[2]; /* events we want to monitor */
35 struct kevent evlist
[2]; /* events that were triggered */
37 int sckfd
, kq
, nev
, i
;
39 /* check argument count */
41 fprintf(stderr
, "usage: %s host port\n", argv
[0]);
45 /* open a connection to a host:port pair */
46 sckfd
= tcpopen(argv
[1], atoi(argv
[2]));
48 /* create a new kernel event queue */
49 if ((kq
= kqueue()) == -1)
52 /* initialise kevent structures */
53 EV_SET(&chlist
[0], sckfd
, EVFILT_READ
, EV_ADD
| EV_ENABLE
, 0, 0, 0);
54 EV_SET(&chlist
[1], fileno(stdin
), EVFILT_READ
, EV_ADD
| EV_ENABLE
, 0, 0, 0);
58 nev
= kevent(kq
, chlist
, 2, evlist
, 2, NULL
);
64 if (evlist
[0].flags
& EV_EOF
) /* read direction of socket has shutdown */
67 for (i
= 0; i
< nev
; i
++) {
68 if (evlist
[i
].flags
& EV_ERROR
) { /* report errors */
69 fprintf(stderr
, "EV_ERROR: %s\n", strerror(evlist
[i
].data
));
73 if (evlist
[i
].ident
== sckfd
) { /* we have data from the host */
74 memset(buf
, 0, BUFSIZE
);
75 if (read(sckfd
, buf
, BUFSIZE
) < 0)
80 else if (evlist
[i
].ident
== fileno(stdin
)) { /* we have data from stdin */
81 memset(buf
, 0, BUFSIZE
);
82 fgets(buf
, BUFSIZE
, stdin
);
83 sendbuftosck(sckfd
, buf
, strlen(buf
));
93 void diep(const char *s
)
99 int tcpopen(const char *host
, int port
)
101 struct sockaddr_in server
;
105 if ((hp
= gethostbyname(host
)) == NULL
)
106 diep("gethostbyname()");
108 if ((sckfd
= socket(PF_INET
, SOCK_STREAM
, 0)) < 0)
111 server
.sin_family
= AF_INET
;
112 server
.sin_port
= htons(port
);
113 server
.sin_addr
= *((struct in_addr
*)hp
->h_addr
);
114 memset(&(server
.sin_zero
), 0, 8);
116 if (connect(sckfd
, (struct sockaddr
*)&server
, sizeof(struct sockaddr
)) < 0)
122 void sendbuftosck(int sckfd
, const char *buf
, int len
)
128 if ((bytessent
= send(sckfd
, buf
+ pos
, len
- pos
, 0)) < 0)
131 } while (bytessent
> 0);