我正在尝试为 Freenode 创建 IRC 客户端
我的代码是这样的:
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);
}
}
我希望能够使用 send()
使用 scanf()
进行用户输入,但我无法在内部使用 scanf()
循环,因为它会阻止套接字接收数据,直到 scanf()
接收到输入。有什么方法可以让循环继续接收数据而不停止等待用户输入吗?
最佳答案
您正在寻找的是 select
系统调用。下面是它的使用示例(使用 write
和 read
而不是 send
和 recv
):
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
}
}
select
系统调用允许您监视多个文件描述符。在这种情况下,如果您想同时监视 stdin 和套接字,则可以将它们放在一组文件描述符上。代码中的注释应该有助于理解它是如何工作的。干杯!
关于c - 如何在同一套接字上循环发送 send() 和 receive() ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59459197/