全部。
我对使用 P 线程库和 BSD 套接字的基于 unix 的聊天室有一个小问题。
此时,客户端可以连接到服务器,使用所需的用户名登录,然后选择要加入的房间。此外,可以将消息发送到服务器,并将收到的消息正确打印到屏幕上。这都是基于文本的。
在客户端程序中,有一个主线程,允许用户按下字符,然后将其推送到向量上;它看起来像这样:
std::vector<char> current_message;/*global*/
while(1)
{
c = '\0';
while(c != '\n')/*Break when enter is pressed(send message)*/
{
c = my_getch();
if((c == '\n' && current_message.size() == 0)/*Cannot send blank messages*/
|| (c == 127 && char_count == 0))
{
c = '\0';
continue;
}
if(!my_isarrow(c))
{
if(c != 127)
char_count++;
else char_count--;
printf("%c", c);
current_message.push_back(c);
}
if(current_message.size() == 250)/*Send the message if close to buf size*/
c = '\n';
}
send_message(current_message, server);
current_message.clear();/*remove characters from already-sent buffer*/
}
还有一个线程过程从服务器检索消息这个过程是必需的,因为我们需要允许客户端同时发送消息,同时他正在等待来自服务器的消息。
该过程如下所示:
void *get_messages(void *data)
{
pthread_detach(pthread_self());/*detach the thread*/
int *sock = (int *) data;/*the thread data passed in is actually a socket
which we use to retrieve messages from server*/
while(1)
{
packet_t pkt;
read(*sock, &pkt, sizeof(packet_t));/*block until a message is received*/
for(int i = 0; i < strlen(pkt.user_name); i++)
{
if(pkt.user_name[i] == '\n')
pkt.user_name[i] = '\0';
}
pthread_mutex_lock(&lock);
chat_buffer.push_back(pkt);
for(int i = 0; i < 50; i++)
printf("\n");/*emulate clearing of terminal window*/
for(int i = 0; i < chat_buffer.size(); i++)/*chat_buffer is a global vector*/
/*that contains all received messages*/
{
for(int j = 0; j < strlen(chat_buffer[i].msg); j++)
{
if(chat_buffer[i].msg[j] == '\n')/*remove newlines(inefficient)*/
chat_buffer[i].msg[j] = '\0';
}
/*print out all received messages to the client terminal*/
printf("%s: %s\n", chat_buffer[i].user_name, chat_buffer[i].msg);
}
printf("----------------------------------------------------\n");/*some formatting for readability*/
for(int i = 0; i < current_message.size(); i++)
printf("%c", current_message[i]); *******This is the problem area*******
}
当一个客户(我)输入了一些字母并将它们推送到缓冲区时,程序中的问题就会出现。并且,与此同时,我们收到了来自服务器的消息,并且屏幕正在“刷新”。您可以看到 get_messages(void *) 过程中发生了什么。但是,当发生此屏幕刷新时,我不希望我(我)客户已经输入的字母消失;为了解决这个问题,我添加了一行代码,它打印出当前在我的 current_message 向量中的所有字母。但是,字母并没有打印出来(即使这里的代码清楚地说明它们应该打印出来) 注意:在我按下键盘上的某个键后,缓冲区中的字符就会显示出来。
我的 getch() 函数的代码如下所示:
int my_getch()/*This actually didn't come from my brain*/
{
struct termios oldt, newt;
int ch;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return ch;
}
此外,my_isarrow 函数只是解析传入的字符以查看它是否是箭头键。我想忽略箭头键,因为它会上下移动光标(我不想要这个。)
那么,有没有人遇到过这个问题,或者任何人都可以在这里看到他们已经处理过的问题?
问候,威廉。