Komunikator p2p z wykorzystaniem boost.asio

Odpowiedz Nowy wątek
2015-02-16 16:17
0

Witam!

Chce napisać komunikator, który umożliwia komunikację pomiędzy dwa hostami w sieci lokalnej. Moim zamierzeniem jest napisać prostego klienta, prosty serwer i wrzucić to do dwóch wątków, tak aby możliwe było jednoczesne odbieranie i wysyłanie danych. Napisałem, krótki kod, który już działa jednak mam problem z paroma rzeczami.

Po pierwsze chciałbym to opakować w klasy. Czyli dla serwera i klienta tworzymy klase i w zależności co chcemy mieć tworzymy dwa obiekty za pomocą, różniących się minimalnie konstruktorów(np. bool czy_serwer = true). I tutaj głównie problem polega na implementacji tego w Boost.Asio. Jesli ktoś ma jakieś wskazówki, gotowe przykłady itp. byłbym wdzięczy. (główny problem to wątki i współbieżne działanie obiektu klienta i serwer)

Kolejną rzeczą jest wysyłanie wiadomości. Przed wysłaniem wiadomość szyfruję i wtedy strona odbierająca musi ją rozszyfrować(to już mam wstępnie zaimplementowane). Jednocześnie pisząc i odbierając wiadomości w konsoli, tekst się może niestey nałożyć na siebie(napisze połowe wiadomości i w tym momencie odbieram nową). Dlatego chce korzystać z np. ncurses i każdą wiadomość odebraną wyświetlać w wyodrębnionym fragmencie konsoli. Mam tutaj problem jak dostać się do każdej wiadomości odbieranej przez serwer(zmienna globalna?).

Wrzucam kod serwera i klienta który mam. Każda wskazówka, rada, link (i gotowe rozwiązania takżę! :) ) będą cenne.

#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/array.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp> 
#include <boost/thread.hpp>
#include <iostream>
#include <string>
const int size_buff = 30;
void nadaj(std::string host, int port) {
        std::string message;
        boost::asio::io_service ios;
        boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(host), port);
        boost::array<char, size_buff> buf;

        while (true) {
            std::getline(std::cin, message, '\n');
            if(message.length()>=(size_buff-1)){
                message.erase(size_buff-1);
            }
            message += "\n";

            boost::asio::ip::tcp::socket socket(ios);
            socket.connect(endpoint);
            std::copy(message.begin(),message.end(),buf.begin());
            boost::system::error_code error;
            socket.write_some(boost::asio::buffer(buf, message.size()), error);

            message.clear();
            socket.close(); 
        }
}

size_t read_complete(char * buff, const boost::system::error_code & err, size_t bytes) {
    if ( err) return 0;
    bool found = std::find(buff, buff + bytes, '\n') < buff + bytes;
    return found ? 0 : 1;
}

void odbior(std::string host, int port) {
    boost::asio::io_service service;
    boost::asio::ip::tcp::acceptor acceptor(service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(host), port));
    char buff[size_buff];
    while ( true) {
    boost::asio::ip::tcp::socket sock(service);
    acceptor.accept(sock);
    int bytes = read(sock, boost::asio::buffer(buff), boost::bind(read_complete,buff,_1,_2));
    std::string msg(buff, bytes-1);
    std::cout << msg << std::endl;
    //memset( buff, 0, sizeof(buff) );
    sock.close();
    }
}

int main()
{
    boost::thread t1(nadaj, "127.0.0.1", 1990);
    boost::thread t2(odbior, "127.0.0.1", 1990);

    t1.join();
    t2.join();

}

Pozostało 580 znaków

2015-02-16 19:53
0

Nie potrzebujesz wątków. Boost Asio bardzo dobrze wspiera programowanie asynchroniczne na jednym wątku. Podejrzyj sobie np. kod serwera http i zobacz jakich rozwiązań użyli: http://www.boost.org/doc/libs[...]/examples/cpp11_examples.html
W razie problemów pytaj:)


Pozostało 580 znaków

2015-02-16 20:05
0

Przede wszystkim jeśli piszesz w asio to dlaczego nie użyjesz proactor pattern? Proactor (o ile to możliwe) zredukuje liczbę wątków do 1 przez co będziesz miał tylko 1 obiekt io_service. Innymi słowy będziesz musiał miał jednego polla/selecta.
Po drugie dlaczego nie chciało ci się poszukać na własną rękę przykładów kodu w asio? Boost ma bardzo dobrą dokumentację, więc nie trudno o jakiś snippet: http://www.boost.org/doc/libs[...]/examples/cpp11_examples.html [szczególnie przykład chata].
Po trzecie nie potrzebujesz używać zmiennych globalnych. Musisz tylko jakoś przekazywać otrzymywane od serwera wiadomości do jakiś obiektów, które komunikują się z właściwą częścią aplikacji (tą, która ma wyświetlać je w danej części okna).

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0