所以,我正在尝试进行c ++ WinSock2聊天,只是为了学习。 它是一个控制台应用程序,我想接受用户输入(发送给对方),但我仍然希望能够回复。 (所以你可以写一条消息,同时仍然能够回复一条消息)......
当使用cin >> input;
时,程序“暂停”直到用户输入了某些东西,这样它就是“回合制”(一个用户写东西并发送它,然后另一个用户写东西并发送它)。
有没有办法让用户能够在recive的东西仍在运行时写点东西? (最好不要多线程)
答案 0 :(得分:3)
检查缓冲区是否空了怎么办?但是代码并不是真正可移植的,因为你知道需要进行一些系统调用。见this。
但也许你可以用一些C代码来做,我会做一些研究并更新我的答案。
stdin
准备好阅读,这就是我们所需要的。
但看起来它不适用于C ++流,所以你只需要使用C代码进行阅读。
让我们跳到定义:
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)
好的,我们只需要检查读取缓冲区,因此writefds
和errorfds
可以是NULL
。我们只需要检查stdin
,因此nfds
为1
(fds
es的数量
超时怎么样?它应该是0
,因此我们需要初始化变量struct timeval timeout
,并在timeout.tv_sec = 0
和timeout.tv_usec = 0
之前将秒和纳秒设置为0。
所以,只留下readfds
。它也非常简单:我们需要初始化变量,"零"它,并添加stdin
可以使用fd_set readfds
,FD_ZERO(&readfds)
和FD_SET(STDIN_FILENO, &readfds)
完成此操作。
好的,最后一步:函数调用。它应该是select(1, &readfds, NULL, NULL, &timeout)
。
如果输入缓冲区为空,则返回0
,如果输入缓冲区为空则返回1
。
UPD2:看起来它不是C ++流,发生了奇怪的事情,当第一次调用缓冲区为空时它会中断。我会尝试解决问题。
UPD3:好的,现在我明白了。看起来您可以将select
与C ++流一起使用。
Select
非常奇怪(恕我直言)功能:重置readfds
。我不确定如何阻止它执行此操作,因此我只使用了一个fd_set
变量来保存它,因此您需要在fd_set savefds = readfds
初始化后添加readfds
,并且每次通话后readfds = savefds
。这是一个糟糕的解决方案,但我不知道如何改进它。
所以代码是:
初始化:
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(STDIN_FILENO, &readfds);
fd_set savefds = readfds;
超时初始化:
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
用法:
if (select(1, &readfds, NULL, NULL, &timeout)) {
cin >> input;
send(input);
}
readfds = savefds;
UPD4:别忘了加入unistd.h
和cstdlib
答案 1 :(得分:0)
above answer很有帮助。
以下是示例(来自SELECT man page的基本代码):
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
int main(void)
{
fd_set rfds, save_rfds;
struct timeval tv;
int retval;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Make a copy of rfds, as after running select, it gets reset */
save_rfds = rfds;
/* Wait for zero seconds. */
tv.tv_sec = 0;
tv.tv_usec = 0;
while(true){
retval = select(1, &rfds, NULL, NULL, &tv);
rfds = save_rfds;
if (retval == -1)
perror("select()");
else if (retval){
/* Runs as soon as you enter a value and press enter. */
std::cout<<"Data is available now.\n";
std::string s;
getline(std::cin, s);
std::cout<<"Data Input: "<<s<<"\n";
/* FD_ISSET(0, &rfds) will be true. */
}
}
exit(EXIT_SUCCESS);
}