按“顺序”呈现发送和接收的聊天消息。对于客户端和服务器

发布于 2024-10-05 00:01:10 字数 2233 浏览 9 评论 0原文

我有一个简单(非常简单:))客户端和服务器,可以通过 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;

I have a simple (very simple:) ) client and server which can send text messages over TCP, It's flawed because I don't know how to listen to the messages and print them on the screen as well as send messages at the same time (for both client and server).

Also I have difficulty in presenting all the sent and received messages between the client and server in the order the messages were sent.

For example on the server side the chat may look like this

Server:Hi there
Client:Hi

And on the client side the same chat looks like this

Client:Hi
Server:Hi there

The messages are in different order and both users see differently. My main question is, how would I go about synchronizing the output so that they both see the same thing?

Keeping in mind what I mentioned earlier about not knowing how to listen and send simultaneously, this is the message loop for the sever and client.

Server message loop

    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;
        }
    }

Client message loop

    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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

桃酥萝莉 2024-10-12 00:01:10

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

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

这是一个使用<的示例聊天客户端/服务器程序代码>选择。 (示例是Python而不是C++,但原理是一样的)。


Windows 特定

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

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

The core problem is how to wait for incoming messages and for user input at the same time. (Once you'll be able to do it, the "synchronization" will follow naturally, since messages will be displayed as they are sent or received).

The solution to this problem is using select. select can wait for input on several file handles (e.g. standard input and a socket) and return when there's data available. You can then handle the data: if it's from the socket, display it. If it's from the user, send it to the remote host.

Here's an example chat client/server program using select. (The example is in Python not C++, but the principle is the same).


Windows-specific

In Windows, select() is provided by the Winsock library and only works on sockets. To wait for input from the console and from a network socket, it looks like you will need to use a combination of WaitForMultipleObjects, GetStdHandle and WSAEventSelect. In Unix-like environments it's much simpler because the standard input and sockets are all file descriptors.

A simpler solution in Windows would be a message-passing based one. Use a window for the text input, and use WSAAsyncSelect to get a message when network input is ready.

伴我老 2024-10-12 00:01:10

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

  1. 服务器发送某种标识聊天消息的标头,其内容为“嗨,那里”。
  2. 客户端收到聊天消息,并使用不同的标头进行回复以表示确认。
  3. 服务器接收客户端的确认,然后将消息打印到屏幕上。

从技术上讲,操作系统已经将其作为 TCP 的一部分来执行此操作,但这可能是在应用程序级别完成类似操作的最简单方法。

In some sense, this is a question about internet protocols. Most application protocols would solve this by including a kind of acknowledgment response when the message successfully reaches its definition. Such a communication might look something like this:

  1. Server sends some kind of header identifying a chat message, with the contents "Hi there".
  2. Client receives chat message, and replies with a different header indicating acknowledgment.
  3. Server receives the client's acknowledgment, and then prints the message to the screen.

The operating system technically already does this as part of TCP, but this is probably the easiest way to accomplish something similar at the application level.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文