光标与curses.h库一起跳转

时间:2011-12-06 02:53:37

标签: c multithreading sockets semaphore

我有一个使用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();

    } 

1 个答案:

答案 0 :(得分:1)

鉴于您的程序存在大量限制,我认为您可以做的绝对最佳是将所有 curses函数限制为单线程 - 所有输入,所有输出,所有重新绘制等。保持IO线程专用于网络IO,绝不是任何基于curses的控制台IO。因为我所关注的平台上的库存诅咒不支持多线程操作,所以仍然无法保证你能以这种方式编写无错误的程序,但它是你最好的镜头。

类似的,更多的Unix-ish方法,是使用多个进程而不是线程。这样,受保护的内存不会让不同的进程意外地在curses全局或静态存储上乱写,并且您有更好的机会编写无错误的软件。

当然,大多数 Unix-ish方法将使用libeventlibev来复用一个线程和一个进程中的所有IO。 (但是这也可能在使用curses时遇到了麻烦。这是三十年前植根于它的神奇软件......)