【发布时间】:2017-07-10 15:32:00
【问题描述】:
正在完成一项课堂作业,并且已经与 ncurses 斗争了一段时间(这对我来说是新的)。创建一个能够通过网络与同一程序的另一个实例进行通信的程序。该程序的一部分是从键盘交互地获取字符并将它们发送到接收端。 (我们被建议使用单线程方法并在 ncurses 中使用 getch,并使用来自 getch 的非阻塞输入)。
我遇到的问题是我的getch 有我无法弄清楚的行为。在不同的变体中,它要么显示我键入的每个其他字符,并且在键入另一个字符之前不会显示最近键入的字符。我使用nodelay() 来获取实时输入,但是。
这是我的 ncurses 显示器的设置。 (注意:我使用了noecho(),因为稍后我不想显示输入的每个字符)。
/* initialize ncurses */
setlocale(LC_ALL,"");
initscr();
cbreak();
noecho();
nodelay(stdscr, TRUE);
nonl();
intrflush(stdscr, FALSE);
keypad(stdscr, TRUE);
clear();
这是我编写的代码,可用于getch 并通过套接字发送/接收数据。
while(1) {
rfdset = master;
if (select(maxfd + 1, &rfdset, NULL, NULL, NULL) < 0) {
perror("select");
exit(EXIT_FAILURE);
}
ch = getch();
if (ch != ERR) {
printw("%c",ch);
write(direct, &ch, 1); // direction to send data
}
for(i = 0; i <= maxfd; i++) {
if (FD_ISSET(i, &rfdset)) {
bzero(msgbuf, MSGSIZE);
idx = read(i, msgbuf, MSGSIZE);
if (i != STDIN)
printw("%s",msgbuf); // display received msg
}
}
}
当我在应用程序的任何一端运行并输入数据时,我得到如下结果:
Computer 1 keyboard input: testing123
Computer 1 screen display: tsig2
Computer 2 message recv'd: tsig2
因此,我确信getch 导致了我的大部分问题,而且我在实施过程中一定遗漏了或做错了什么。任何建议表示赞赏。
编辑 1:
我设法通过删除 for 循环并直接检查套接字的输入来解决 所有其他字符问题。我很困惑为什么这会解决它。现在我唯一剩下的问题是为什么在输入字符后才显示字符。这是我在while循环中修改的代码:
while(1) {
rfdset = master;
if (select(maxfd + 1, &rfdset, NULL, NULL, NULL) < 0) {
perror("select");
exit(EXIT_FAILURE);
}
ch = getch();
if (ch != ERR) {
printw("%c",ch);
write(direct, &ch, 1);
}
/* check for incoming data from left socket */
if (!NOLEFT && FD_ISSET(lcsad, &rfdset)) {
bzero(leftmsg, MSGSIZE);
idx = read(lcsad, leftmsg, MSGSIZE);
leftmsg[idx] = 0;
printw("%s", leftmsg);
lm = 1;
}
/* check for incoming data from right socket */
if (!NORIGHT && FD_ISSET(rsd, &rfdset)) {
bzero(rghtmsg, MSGSIZE);
idx = read(rsd, rghtmsg, MSGSIZE);
rghtmsg[idx] = 0;
printw("%s", rghtmsg);
rm = 1;
}
/* check and send left message onward */
if (lm && !NORIGHT) {
write(direct, leftmsg, MSGSIZE);
}
/* check and send right message onward */
if (rm && !NOLEFT) {
write(direct, rghtmsg, MSGSIZE);
}
lm, rm = 0;
}
【问题讨论】:
-
请注意,
msgbuf不一定是空字符终止的。建议read(i, msgbuf, MSGSIZE-1); -
对于调试,在输出中添加括号可能会很有用。
printw("%c",ch);-->printw("<%c>",ch);和printw("<%s>",msgbuf); -
谢谢@chux,这是一个很好的观点,我需要解决一些问题。 (也感谢您的编辑)。我会试试的。
-
@chux - 所以我把括号放在里面,这是我输入“测试键盘输入”
<t><s>< ><e><b><a><d><i><p><t>< >得到的结果,两台机器上的结果都是一样的。 -
关于所有其他字符问题。代码读取
ch = getch();,然后在for循环中读取idx = read(0, msgbuf, MSGSIZE);。这不也是stdin的读法吗?