📜  使用C++ boost :: asio的同步聊天应用程序

📅  最后修改于: 2021-05-30 02:29:52             🧑  作者: Mango

Boost库由asio组成,后者是一个免费的跨平台C++库,用于网络和底层I / O编程,它使用现代C++方法提供一致的异步模型。本文将帮助使用boost :: asio开发客户端-服务器同步聊天应用程序。我们明确提到“同步”,因为在同步模型中,我们的一个客户端或服务器必须等待另一个。
服务器端应用程序:以下是创建服务器端应用程序的各个步骤:

  • 导入boost / asio.hpp(版本:1.65.1.0)
#include 
  • 创建io_service对象(用于服务器),这对于使用boost :: asio是必不可少的。
boost::asio::io_service io_service_object;
  • 创建接收器的对象,传递io_service对象和连接的端点,即IPv4和端口号9999(boost :: asio也支持IPv6协议,还请注意,保留了端口0 – 1233)。
boost::asio::ip::tcp::acceptor 
  acceptor_object(
    io_service_object, 
    tcp::endpoint(boost::asio::ip::tcp::v4(), 
                  9999));
  • 为我们的服务器创建tcp :: socket对象。
boost::asio::ip::tcp::socket socket_object(io_service_object) 
  • 调用接受者对象的接受方法来建立连接。
acceptor_server.accept(server_socket);
  • read_until()方法从缓冲区中获取消息,该缓冲区在通信期间存储数据。在这里,我们使用“ \ n”作为出界符,这意味着我们将继续从缓冲区读取数据,直到遇到“ \ n”并将其存储为止。
// Create buffer for storing
boost::asio::streambuf buf;

boost::asio::read_until(socket, buf, "\n");
string data = boost::asio::buffer_cast(buf.data());
  • write()方法以套接字对象和消息为参数将数据写入缓冲区。
boost::asio::write(
  socket, 
  boost::asio::buffer(message + "\n"));

客户端应用程序:以下是创建客户端应用程序的各个步骤:

  • 导入boost / asio.hpp。
#include 
  • 为客户端创建io_service的对象。
boost::asio::io_service io_service_object;
  • 为客户端创建tcp :: socket对象。
boost::asio::ip::tcp::socket
  socket_object(io_service_object) 
  • 调用套接字对象的connect方法以使用localhost(IP 127.0.0.1)启动与服务器的连接,并连接到相同的端口9999。
client_socket.connect(
  tcp::endpoint(
    address::from_string("127.0.0.1"), 
    9999 ));
  • 对于我们的客户端应用程序,与服务器端一样,read_until()和write()也将保持不变。

下面是上述方法的实现:程序:

server.cpp
// Server-side Synchronous Chatting Application
// using C++ boost::asio

#include 
#include 

using namespace std;
using namespace boost::asio;
using namespace boost::asio::ip;

// Driver program for receiving data from buffer
string getData(tcp::socket& socket)
{
    streambuf buf;
    read_until(socket, buf, "\n");
    string data = buffer_cast(buf.data());
    return data;
}

// Driver program to send data
void sendData(tcp::socket& socket, const string& message)
{
    write(socket,
          buffer(message + "\n"));
}

int main(int argc, char* argv[])
{
    io_service io_service;

    // Listening for any new incomming connection
    // at port 9999 with IPv4 protocol
    tcp::acceptor acceptor_server(
        io_service,
        tcp::endpoint(tcp::v4(), 9999));

    // Creating socket object
    tcp::socket server_socket(io_service);

    // waiting for connection
    acceptor_server.accept(server_socket);

    // Reading username
    string u_name = getData(server_socket);
    // Removing "\n" from the username
    u_name.pop_back();

    // Replying with default message to initiate chat
    string response, reply;
    reply = "Hello " + u_name + "!";
    cout << "Server: " << reply << endl;
    sendData(server_socket, reply);

    while (true) {

        // Fetching response
        response = getData(server_socket);

        // Popping last character "\n"
        response.pop_back();

        // Validating if the connection has to be closed
        if (response == "exit") {
            cout << u_name << " left!" << endl;
            break;
        }
        cout << u_name << ": " << response << endl;

        // Reading new message from input stream
        cout << "Server"
             << ": ";
        getline(cin, reply);
        sendData(server_socket, reply);

        if (reply == "exit")
            break;
    }
    return 0;
}

client.cpp
// Client-side Synchronous Chatting Application
// using C++ boost::asio

#include 
#include 
using namespace std;
using namespace boost::asio;
using namespace boost::asio::ip;

string getData(tcp::socket& socket)
{
    streambuf buf;
    read_until(socket, buf, "\n");
    string data = buffer_cast(buf.data());
    return data;
}

void sendData(tcp::socket& socket, const string& message)
{
    write(socket,
          buffer(message + "\n"));
}

int main(int argc, char* argv[])
{
    io_service io_service;
    // socket creation
    ip::tcp::socket client_socket(io_service);

    client_socket
        .connect(
            tcp::endpoint(
                address::from_string("127.0.0.1"),
                9999));

    // Getting username from user
    cout << "Enter your name: ";
    string u_name, reply, response;
    getline(cin, u_name);

    // Sending username to another end
    // to initiate the conversation
    sendData(client_socket, u_name);

    // Infinite loop for chit-chat
    while (true) {

        // Fetching response
        response = getData(client_socket);

        // Popping last character "\n"
        response.pop_back();

        // Validating if the connection has to be closed
        if (response == "exit") {
            cout << "Connection terminated" << endl;
            break;
        }
        cout << "Server: " << response << endl;

        // Reading new message from input stream
        cout << u_name << ": ";
        getline(cin, reply);
        sendData(client_socket, reply);

        if (reply == "exit")
            break;
    }
    return 0;
}