Open In App

Synchronous Chatting Application using C++ boost::asio

Boost library consists of asio which is a free, cross-platform C++ library for network and low-level I/O programming that provides a consistent asynchronous model using a modern C++ approach. This article will help to develop a client-server synchronous chatting application using boost::asio. We are explicitly mentioning “synchronous” because in the synchronous model one of our client or server has to wait for another. 
Server-Side Application: Below are the various steps to create the Server Side application:
 

#include <boost/asio.hpp>
boost::asio::io_service io_service_object;
boost::asio::ip::tcp::acceptor 
  acceptor_object(
    io_service_object, 
    tcp::endpoint(boost::asio::ip::tcp::v4(), 
                  9999));
boost::asio::ip::tcp::socket socket_object(io_service_object) 
acceptor_server.accept(server_socket);
// Create buffer for storing
boost::asio::streambuf buf;

boost::asio::read_until(socket, buf, "\n");
string data = boost::asio::buffer_cast(buf.data());
boost::asio::write(
  socket, 
  boost::asio::buffer(message + "\n"));

Client-Side Application: Below are the various steps to create the Client Side application: 
 



#include <boost/asio.hpp>
boost::asio::io_service io_service_object;
boost::asio::ip::tcp::socket
  socket_object(io_service_object) 
client_socket.connect(
  tcp::endpoint(
    address::from_string("127.0.0.1"), 
    9999 ));

Below is the implementation of the above approach: Program: 

server.cpp


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

#include <boost/asio.hpp>
#include <iostream>

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<const char*>(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 <boost/asio.hpp>
#include <iostream>
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<const char*>(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;
}

$ g++ client.cpp -o client -lboost_system
./client
$ g++ server.cpp -o server -lboost_system
./server

The above socket programming explains our simple synchronous TCP server and client chatting application. One of the major drawbacks of the synchronous client-server application is that one request has to be served before we request for another one, thus blocking our later requests. In case we want our program to perform multiple operations simultaneously, we can use multi-threaded TCP client-server to handle the situation. However, the multi-threaded application is not recommended because of various complexities involved in creating threads. Another option can come handy, and that is the asynchronous server. This is where boost::asio shines, we shall understand this in the next article.
 

Article Tags :
C++