以“顺序”为客户端和服务器呈现发送和接收的聊天消息

时间:2010-11-28 07:43:16

标签: c++ gcc synchronization chat winsock

我有一个简单的(非常简单的:)客户端和服务器,它可以通过TCP发送文本消息,它有缺陷,因为我不知道如何收听消息并在屏幕上打印它们以及发送消息同时(对于客户端和服务器)。

此外,我很难按照邮件发送的顺序在客户端和服务器之间显示所有已发送和已接收的邮件

例如,在服务器一侧,聊天可能如下所示

Server:Hi there
Client:Hi

客户端方面,同一个聊天就像这样

Client:Hi
Server:Hi there

消息的顺序不同,两个用户的看法不同。 我的主要问题是,我将如何同步输出,以便他们看到同样的事情?

请记住我之前提到的关于不知道如何同时监听和发送的内容,这是服务器和客户端的消息循环。

服务器消息循环

    while(true){
        cout<<"-[SERVER]: ";
        getline(cin,send_text);
        if (sizeof(send_text) > 0 ){
            bytes_out = send(client,send_text.c_str(),send_text.length()+1,0);
            cout<< endl;
            if (bytes_out == SOCKET_ERROR){
                cout<<"-[SERVER error in sending.]" << endl;
                break;
            }
        }

        bytes_in = recv(client,recvd_text,sizeof(recvd_text),0);
        if (bytes_in > 0 ){
            cout<<"-[CLIENT]: " << recvd_text << endl;  //output on screen
        }
        if (bytes_in == 0){
            cout<<"-[CLIENT has disconnected.]" << endl;
            break;
        }
        if (bytes_in == SOCKET_ERROR){
            cout<<"-[CLIENT closed unexpectedly.]" << endl;
            break;
        }
    }

客户端消息循环

    while (true){
        cout<<"-[CLIENT]: ";
        getline(cin,send_text);
        if(sizeof(send_text) > 0){
            bytes_out = send(con_sock,send_text.c_str(),send_text.length()+1,0);
            if (bytes_out == SOCKET_ERROR){
                cout<<"-[CLIENT error in sending.]" << endl;
                break;
            }
        }

        bytes_in = recv(con_sock,recvd_text,sizeof(recvd_text),0);
        if (bytes_in > 0){
            cout<<"-[SERVER]: " << recvd_text << endl;
        }
        if (bytes_in == 0){
            cout<<"-[Server has disconnected." << endl;
            break;
        }
        if (bytes_in == SOCKET_ERROR){
            cout<<"-[Server closed unexpectedly." << endl;
            break;
        }
    }
    return true;

2 个答案:

答案 0 :(得分:1)

核心问题是如何同时等待传入消息和用户输入。 (一旦你能够做到这一点,“同步”将自然而然地发生,因为消息将在发送或接收时显示)。

此问题的解决方案是使用selectselect可以等待几个文件句柄(例如标准输入和套接字)的输入,并在有可用数据时返回。然后,您可以处理数据:如果它来自套接字,则显示它。如果是来自用户,请将其发送到远程主机。

Here's使用select的示例聊天客户端/服务器程序。 (例子是Python而不是C ++,但原理是一样的。)


Windows特定

在Windows中,select()由Winsock库提供,仅适用于套接字。要等待来自控制台和网络套接字的输入,您似乎需要使用WaitForMultipleObjectsGetStdHandleWSAEventSelect的组合。在类Unix环境中,它更简单,因为标准输入和套接字都是文件描述符。

Windows中一个更简单的解决方案是基于消息传递的解决方案。使用窗口输入文本,并在网络输入准备就绪时使用WSAAsyncSelect获取消息。

答案 1 :(得分:0)

从某种意义上说,这是一个关于互联网协议的问题。大多数应用程序协议通过在消息成功到达其定义时包含一种确认响应来解决此问题。这样的沟通可能看起来像这样:

  1. 服务器发送某种标识聊天消息的标题,内容为“Hi there”。
  2. 客户端收到聊天消息,并使用指示确认的其他标头进行回复。
  3. 服务器收到客户端的确认,然后将消息打印到屏幕上。
  4. 操作系统在技术上已经将此作为TCP的一部分,但这可能是在应用程序级别完成类似操作的最简单方法。