2

the question is, how can I connect one program between two or more computers over a network, in other words, I want to create a dialog application on Windows in cmd (yes, the idea can be strange and stupid, but it just arouses incredible interest in me). I tried to create a connection between the host and the server, but firstly, I did not succeed (maybe I misunderstood this method), and secondly, I think, I need a host to host connection

That's all the code I came up with, in general there were many implementations of how to connect, but none of them fit or did not work


#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")

#include <iostream>
#include <boost/asio.hpp>
#include <fstream>
#include <ctime>
#include <time.h>
#include <boost/bind/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

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

string message;
string nickname;

string Mess(string name, string text);

class tcp_connection
  : public boost::enable_shared_from_this<tcp_connection>
{
public:
    typedef boost::shared_ptr<tcp_connection> pointer;

    static pointer create(boost::asio::io_context& io_context)
    {
    return pointer(new tcp_connection(io_context));
    }

    tcp::socket& socket()
    {
    return socket_;
    }

    void start()
    {
        message_ = Mess(nickname, message);

        boost::asio::async_write(socket_, boost::asio::buffer(message_),
            boost::bind(&tcp_connection::handle_write, shared_from_this(),
              boost::asio::placeholders::error,
              boost::asio::placeholders::bytes_transferred));
    }

private:
    tcp_connection(boost::asio::io_context& io_context)
    : socket_(io_context)
    {

    }

    void handle_write(const boost::system::error_code& /*error*/,
      size_t /*bytes_transferred*/)
    {

    }

    tcp::socket socket_;
    std::string message_;
};

class tcp_server
{
public:
    tcp_server(boost::asio::io_context& io_context)
    : io_context_(io_context),
      acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
    {
        start_accept();
    }

private:
    void start_accept()
    {
    tcp_connection::pointer new_connection =
      tcp_connection::create(io_context_);

    acceptor_.async_accept(new_connection->socket(),
        boost::bind(&tcp_server::handle_accept, this, new_connection,
          boost::asio::placeholders::error));
    }

    void handle_accept(tcp_connection::pointer new_connection,
      const boost::system::error_code& error)
    {
    if (!error)
    {
      new_connection->start();
    }

    start_accept();
    }

    boost::asio::io_context& io_context_;
    tcp::acceptor acceptor_;
};

string Current_time()
{
    auto start = std::chrono::system_clock::now();
    auto end = std::chrono::system_clock::now();
    
    std::chrono::duration<double> elapsed_sec = end - start;
    std::time_t end_time = std::chrono::system_clock::to_time_t(end);

    return std::ctime(&end_time);

}

string Mess(string name, string text)
{
    string mes = name + ": " + text;
    return mes;
}

int main()
{

    boost::asio::io_context io;
    boost::asio::steady_timer timer(io, boost::asio::chrono::seconds(3));

    io_service serv;
    string ipadress;
    int start;
    ip::tcp::socket socket1(serv);
    ip::tcp::socket socket2(serv);
    tcp_server server(serv);
    serv.run();

    cout << "\n\t\tYou in my Social network\n" << std::endl;

    cout << "\n1 - to start chating, 2 - to exit, 3 - to check your host name: ";
    cin >> start;
    
    if (start == 1)
    {
        cout << "\nWrite your nickname (more than 3 symbols): ";
        cin >> nickname;

        if (nickname.length() <= 3)
        {
            system("cls");
            cout << "\n\n\t\tYour nickname should be more than 3 symbols\n\n\n";
            exit(1);
        }
        else
        {
            system("cls");
            
            //cout << "ip: " << IPad() << endl;

            cout << "Your nick is: '" << nickname << "'";

            tcp_connection tc();

            cout << "\n\nWrite your message (to end, press Ctrl + Z): ";
            cin >> message;

            cout << "\n" << Mess(nickname, message) << "\ttime when sended: " << Current_time() << "\n";

        }
    }
    else if (start == 2)
    {
        timer.wait();
        io.run();
        system("cls");
        exit(1);
    }
    else if (start == 3)
    {
        cout << "\n\tYour host name is: " << boost::asio::ip::host_name() << endl;
    }
    else
    {
        system("cls");
        cout << "\n\n\n\t\t\t1 or 2!!!\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" << endl;
        cout << "bye";
        timer.wait();
        exit(1);
    }


}

1 Answers1

2
  1. Firstly

            tcp_connection tc();
    

    That's a Most Vexing Parse: it declares a function! You need to pass constructor arguments. Also, since shared_from_this is used, you need to use make_shared (or the create helper that you used in the server):

            auto tc = tcp_connection::create(serv);
    
  2. Now things compile, but you "run" the server to completion:

     svc.run();
    

    That blocks until the server exits, so nothing else would run.

    Easiest fix is to make the service a thread_pool.

  3. There is no need to use global variables here (nickname and message belong to a client)

  4. Don't use using namespace - Why is "using namespace std;" considered bad practice?

  5. You have a conceptual problem where since the program unconditionally starts a server you need different machines to test. This may or may not be a real problem for you

Some of the issues fixed:

Live On Coliru

#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <time.h>

namespace asio = boost::asio;
using asio::ip::tcp;

static constexpr uint16_t port = 7878; // 13
std::string               message;
std::string               nickname;

std::string Mess(std::string name, std::string text);

class tcp_connection : public boost::enable_shared_from_this<tcp_connection> {
  public:
    typedef boost::shared_ptr<tcp_connection> pointer;

    static pointer create(asio::any_io_executor ex) {
        return pointer(new tcp_connection(ex));
    }

    tcp::socket& socket() { return socket_; }

    void start() {
        message_ = Mess(nickname, message);

        asio::async_write(socket_, asio::buffer(message_),
                          boost::bind(&tcp_connection::handle_write, shared_from_this(),
                                      asio::placeholders::error,
                                      asio::placeholders::bytes_transferred));
    }

  private:
    tcp_connection(asio::any_io_executor ex) : socket_(ex) {}

    void handle_write(boost::system::error_code /*ec*/, size_t /*transferred*/) {}

    tcp::socket socket_;
    std::string message_;
};

class tcp_server {
  public:
    tcp_server(asio::any_io_executor ex)
        : acceptor_(ex, {{}, port}) //
    {
        start_accept();
    }

  private:
    void start_accept() {
        tcp_connection::pointer new_connection =
            tcp_connection::create(acceptor_.get_executor()); // or make_strand?

        acceptor_.async_accept(new_connection->socket(),
                               boost::bind(&tcp_server::handle_accept, this,
                                           new_connection, asio::placeholders::error));
    }

    void handle_accept(tcp_connection::pointer   new_connection,
                       boost::system::error_code ec) {
        if (!ec) {
            new_connection->start();
        }

        start_accept();
    }

    tcp::acceptor acceptor_;
};

std::string Current_time() {
    // auto start = std::chrono::system_clock::now();
    auto end = std::chrono::system_clock::now();

    // std::chrono::duration<double> elapsed_sec = end - start;
    std::time_t end_time = std::chrono::system_clock::to_time_t(end);

    return std::ctime(&end_time);
}

std::string Mess(std::string name, std::string text) { return name + ": " + text; }

int main() {
    asio::thread_pool svc(1);
    // std::string      ipadress;
    tcp_server server(svc.get_executor());

    tcp::socket socket1(svc);
    tcp::socket socket2(svc);
    std::cout << "\n\tYou in my Social network\n" << std::endl;

    std::cout << "\n1 - to start chatting, 2 - to exit, 3 - to check your host name: ";
    int start;
    std::cin >> start;

    if (start == 1) {
        std::cout << "\nWrite your nickname (more than 3 symbols): ";
        std::cin >> nickname;

        if (nickname.length() <= 3) {
            std::cout << "\n\tYour nickname should be more than 3 symbols" << std::endl;
            exit(1);
        } else {

            // cout << "ip: " << IPad() << endl;

            std::cout << "Your nick is: " << quoted(nickname) << std::endl;

            auto tc = tcp_connection::create(svc.get_executor());

            std::cout << "\nWrite your message (to end, press Ctrl + Z): ";
            std::cin >> message;

            std::cout << "\n"
                      << Mess(nickname, message) << "\ttime when sent: " << Current_time()
                      << std::endl;
        }
    } else if (start == 2) {
        std::this_thread::sleep_for(std::chrono::seconds(3));
    } else if (start == 3) {
        std::cout << "\n\tYour host name is: " << asio::ip::host_name() << std::endl;
    } else {
        std::cout << "\n\t1 or 2!!!\n" << std::endl;
        std::cout << "bye";
        std::this_thread::sleep_for(std::chrono::seconds(3));
        exit(1);
    }
    svc.join();
}

Run with

g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp 
./a.out <<< "1 sehe helloworld!" 

Prints

    You in my Social network


1 - to start chatting, 2 - to exit, 3 - to check your host name: 
Write your nickname (more than 3 symbols): Your nick is: "sehe"

Write your message (to end, press Ctrl + Z): 
sehe: helloworld!   time when sent: Tue Nov 15 14:37:27 2022
sehe
  • 374,641
  • 47
  • 450
  • 633
  • yeah, that works, but on another pc, I don't see the message that I wrote on it and one more thing, will i need to implement a thread pool? – miraculous_guru Nov 15 '22 at 15:56
  • That's because you don't send anything. I've fixed the problems with the code that were visible. If you also wanted the program to do things that you didn't program, perhaps you should try adding that and ask a new question only if you get stuck. – sehe Nov 15 '22 at 16:33