【发布时间】:2016-01-06 05:46:54
【问题描述】:
我为社交网络和简单的基于房间的聊天编写了一个 C 应用程序。我使用了 ncurses、sockets 和基本的网络东西。
问题是我的函数使用 select() 从服务器套接字和标准输入中读取,所以当我开始编写消息时,输出窗口冻结,并且在我按 Enter 后仅显示来自其他客户端的消息。
我尝试了所有可能的方法。有没有办法解决这个问题?
我也尝试强制 nocbreak()。它工作正常,但如果我这样做,当我编写消息时,回显被禁用,并且在我键入时输入窗口中没有任何显示,即使消息在那里但是像“隐形”。
代码如下:
ssize_t safePrefRead(int sock, void *buffer)
{
size_t length = strlen(buffer);
ssize_t nbytesR = read(sock, &length, sizeof(size_t));
if (nbytesR == -1)
{
perror("read() error for length ! Exiting !\n");
exit(EXIT_FAILURE);
}
nbytesR = read(sock, buffer, length);
if (nbytesR == -1)
{
perror("read() error for data ! Exiting !\n");
exit(EXIT_FAILURE);
}
return nbytesR;
}
ssize_t safePrefWrite(int sock, const void *buffer)
{
size_t length = strlen(buffer);
ssize_t nbytesW = write(sock, &length, sizeof(size_t));
if (nbytesW == -1)
{
perror("write() error for length ! Exiting !\n");
exit(EXIT_FAILURE);
}
nbytesW = write(sock, buffer, length);
if (nbytesW == -1)
{
perror("write() error for data ! Exiting !\n");
exit(EXIT_FAILURE);
}
return nbytesW;
}
void activeChat(int sC, const char *currentUser, const char *room)
{
char inMesg[513], outMesg[513];
char user[33];
int winrows, wincols;
WINDOW *winput, *woutput;
initscr();
nocbreak();
getmaxyx(stdscr, winrows, wincols);
winput = newwin(1, wincols, winrows - 1, 0);
woutput = newwin(winrows - 1, wincols, 0, 0);
keypad(winput, true);
scrollok(woutput, true);
wrefresh(woutput);
wrefresh(winput);
fd_set all;
fd_set read_fds;
FD_ZERO(&all);
FD_ZERO(&read_fds);
FD_SET(0, &all);
FD_SET(sC, &all);
wprintw(woutput, "Welcome to room '%s' \n Use /quitChat to exit !\n!", room);
wrefresh(woutput);
while (true)
{
memcpy( &read_fds, &all, sizeof read_fds );
if (select(sC + 1, &read_fds, NULL, NULL, NULL) == -1)
{
perror("select() error or forced exit !\n");
break;
}
if (FD_ISSET(sC, &read_fds))
{
memset(inMesg, 0, 513);
safePrefRead(sC, user);
safePrefRead(sC, inMesg);
wprintw(woutput, "%s : %s\n", user, inMesg);
wrefresh(woutput);
wrefresh(winput);
}
if (FD_ISSET(0, &read_fds))
{
//wgetnstr(winput, "%s", outMesg);
int a, i = 0;
while ( i < MAX_BUF_LEN && (a = wgetch(winput)) != '\n')
{
outMesg[i] = (char)a;
i++;
}
outMesg[i] = 0;
if (outMesg[0] == 0)
continue;
if (strcmp(outMesg, "/quitChat") == 0)
{
safePrefWrite(sC, outMesg);
break;
}
safePrefWrite(sC, outMesg);
delwin(winput);
winput = newwin(1, wincols, winrows - 1, 0);
keypad(winput, true);
wrefresh(winput);
}
}
delwin(winput);
delwin(woutput);
endwin();
}
-safePrefWrite 和 safePrefRead 是用于预读/写和错误处理的包装器 -sC 是服务器套接字。
LE:我尝试使用 fork 和线程。使用 fork 的行为相同,线程是一场灾难,终端被搞砸了。
谢谢。
【问题讨论】:
-
请在此处粘贴您的代码。
-
"我尝试了所有可能的方法......" -- 请在此处说明这些可能性。
-
稍后我将在此处粘贴代码,因为我现在无法这样做。我的意思是强制 echo(),当我用 waddch()、forks、threads 阅读它们时,在 wininput 中逐个字符打印它们。我不记得它们,因为这个问题占用了我生命的 7 个小时。
-
pastebin 代码似乎是从一个较大的文件中提取出来的。除其他事项外,#include 包含哪些头文件?发布的代码是如何被调用的。
-
“远程”用户似乎无法优雅地退出程序。当本地用户退出程序时,本地用户的文本输入会被广播,而不是类似:'
在他们退出房间时挥手告别'
标签: c sockets select networking ncurses