Reputation: 423
I am trying to create an IRC client for Freenode
My code is as such:
while ((numbytes = recv(sockfd, buf, BUFFSIZE -1, 0)) != -1) {
buf[numbytes] = '\0';
printf("client: %s\n", buf);
if (strstr(buf, "Nickname is already in use"))
exit(EXIT_FAILURE);
if (strstr(buf, "PING")) {
num_bytes_sent = send(sockfd, "PONG", 5, 0);
printf("%d PONG\n", num_bytes_sent);
}
}
I want to be able to use send()
for user input using scanf()
, but I cannot use scanf()
inside the loop because it stops the socket from receiving data until scanf()
receives input. Is there any way the loop can continue to receive data without stopping to wait for user input?
Upvotes: 0
Views: 854
Reputation: 1675
What you're looking for is the select
system call. Here is an example of its use (using write
and read
instead of send
and recv
though):
fd_set fds_receive; // set of file descriptors
char buffer[BUFSIZE];
FD_ZERO(&fds_receive); // initialize the set
while (1) {
FD_SET(socket_fd, fds_receive); // monitor the socket
FD_SET(STDIN_FD, fds_receive); // monitor stdin
/* the select system call will return when one of the file
descriptors that it is monitoring is ready for an I/O operation */
if (select(FD_SETSIZE, &fds_receive, NULL, NULL, NULL) < 0) {
perror("select");
exit(-1);
}
// if new data arrives from stdin
if (FD_ISSET(STDIN_FD, &fds_receive)) {
num_bytes = read(STDIN_FD, buffer, sizeof(buffer));
if (num_bytes < 0) { // error in the "read" system call
perror("read");
exit(-1);
} else if (num_bytes == 0) { // "Ctrl+D" pressed, stdin receives 0 bytes
if (close(socket_fd) < 0) {
perror("close");
exit(-1);
}
exit(0);
}
// send data received in stdin to socket
buffer[num_bytes] = '\0';
if (write(socket_fd, buffer, strlen(buffer)+1) < 0) {
perror("write");
exit(-1);
}
}
// if new data arrives from the socket
if (FD_ISSET(socket_fd, &fds_receive)) {
num_bytes = read(socket_fd, buffer, sizeof(buffer));
if (num_bytes < 0) { // error in the "write" system call
perror("read");
exit(-1);
} else if (num_bytes == 0) { // connection terminated, no problem
close(socket_fd);
exit(0);
}
// do stuff with data that arrived from the socket
}
}
The select
system call allows you to monitor multiple file descriptors. In this case, if you want to monitor both stdin
and a socket, you put them on a set of file descriptors. The comments in the code should be helpful in understanding how it works. Cheers!
Upvotes: 1