我有一个使用curses和套接字创建会话程序的项目。基本上,主线程启动两个线程来管理屏幕的两半,另一个线程来管理通过网络发送/接收。代码看起来很干净,但由于某种原因,光标有时会随机跳转到屏幕周围。通常它周围的三行将开始遍布整个地方。我没有来自curses的mv _ __()函数所以我很困惑为什么光标对我来说是流氓。
这是由两个线程调用来管理屏幕两侧的函数。关于可能导致这种情况的任何想法?
void *display(int sub)
{
int bufSize = 10;
char* buf = (char*)calloc(bufSize, sizeof(char));
while(read(displayPipe[sub][0], buf, 1) > 0)
{
sem_wait(&displaySem);
waddch(subWin[sub], buf[0]);
wrefresh(subWin[sub]);
sem_post(&displaySem);
}
free(buf);
return NULL;
}
这是从套接字读取的函数
void *netToPipe()
{
int bufSize = 10;
char* buf = (char*)calloc(bufSize, sizeof(char));
// read from talkfd
while(read(talkfd, buf, 1) != EOF)
{
// print to the bottom of the screen
if(write(displayPipe[1][1], buf, 1) < 0)
(void)printf("Error writing to talkfd\n");
}
free(buf);
return NULL;
}
这是main()的结尾,它从键盘读取并写入屏幕底部(通过管道)和插座。
while(1)
{
// get a key from the subwindow
key = wgetch(subWin[0]);
// we are connected to a client
if(talkfd > 0)
{
// send across network
write(talkfd, &key, 1);
// copy to upper portion of the screen
write(displayPipe[0][1], &key, 1);
}
// we are just talking to self
else
{
// send to bottom of screen
write(displayPipe[1][1], &key, 1);
// send to top of screen
write(displayPipe[0][1], &key, 1);
}
refresh();
}
答案 0 :(得分:1)
鉴于您的程序存在大量限制,我认为您可以做的绝对最佳是将所有 curses
函数限制为单线程 - 所有输入,所有输出,所有重新绘制等。保持IO线程专用于仅网络IO,绝不是任何基于curses
的控制台IO。因为我所关注的平台上的库存诅咒不支持多线程操作,所以仍然无法保证你能以这种方式编写无错误的程序,但它是你最好的镜头。
类似的,更多的Unix-ish方法,是使用多个进程而不是线程。这样,受保护的内存不会让不同的进程意外地在curses
全局或静态存储上乱写,并且您有更好的机会编写无错误的软件。
当然,大多数 Unix-ish方法将使用libevent或libev来复用一个线程和一个进程中的所有IO。 (但是这也可能在使用curses
时遇到了麻烦。这是三十年前植根于它的神奇软件......)