[C++] boost/asio.hpp in Code::Blocks werken krijgen.

Pagina: 1
Acties:

Onderwerpen


  • xehbit
  • Registratie: Februari 2009
  • Laatst online: 26-08 22:19
Beste Tweakers,

Nu ik al een ruime tijd met de lib's van boost bezig ben wou ik eens wat gaan proberen met sockets (asio.hpp) Echter krijg ik daar een hoop foutmeldingen bij wanneer ik alleen dat bestand al include. Deze code met boost werkt wel juist.
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <boost/regex.hpp>
#include <iostream>
#include <string>


int main()
{
    std::string line;
    boost::regex pat( "^Subject: (Re: |Aw: )*(.*)" );

    while (std::cin)
    {
        std::getline(std::cin, line);
        boost::smatch matches;
        if (boost::regex_match(line, matches, pat))
            std::cout << matches[2] << std::endl;
    }
}

De bovestaande code kan ik dus zonder problemen compilen. Dus de boost lib- directories zijn goed.

Maar wanneer ik een include erbij zet: #include <boost/asio.hpp> en de juist lib er bij toevoeg krijg ik de volgende fouten.
obj\Debug\main.o||In function `ZN5boost4asio6detail17winsock_init_base7startupERNS2_4dataEhh':|
C:\SDK\boost_1_47_0\boost\asio\detail\impl\winsock_init.ipp|39|undefined reference to `WSAStartup@8'|
obj\Debug\main.o||In function `ZN5boost4asio6detail17winsock_init_base7cleanupERNS2_4dataE':|
C:\SDK\boost_1_47_0\boost\asio\detail\impl\winsock_init.ipp|48|undefined reference to `WSACleanup@0'|
||=== Build finished: 2 errors, 0 warnings ===|


Toch zijn de lib's included. Maar wat gaat hier fout?
Ik maak gebuik van codeblocks en de MinGW compiler.

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Zorg je ook dat je de winsock libs mee linkt?

  • xehbit
  • Registratie: Februari 2009
  • Laatst online: 26-08 22:19
PrisonerOfPain schreef op donderdag 25 augustus 2011 @ 19:48:
Zorg je ook dat je de winsock libs mee linkt?
Oei, dat is dan waarschijnlijk het probleem. Waar kan ik die libs vinden van de winsock? Of moeten die ook nog apart worden gedownload?
n.v.m. Eerst zelf even googlen 8)7

Edit2: Gevonden! -lws2_32 toevoegen aan de linker's. Bedankt !

Edit 3: Het is (denk ik?) een beetje onnodig om nog een nieuw topic te openen over de sockets, dus vandaar deze edit.

Het volgende probleem is nu dat ik de volgende melding krijg:
D:\Development\Cpp\BoostSocketTest\tcpclient\tcpclient.h|13|error: no matching function for call to 'boost::asio::basic_stream_socket<boost::asio::ip::tcp>::basic_stream_socket()'|


Het vreemde is dat de lijn nr. 13 alleen een '{' staat. Dus geen idee heb wat er fout aan is :| (HELP!!?? 8)7 )
de header file tcpclient.h ziet er zo uit:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#pragma once

#include <iostream>
#include <string>

#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>

using boost::asio::ip::tcp;

class tcpClient
{

public:
    bool Connect(char* host, int port);

private:
    boost::asio::ip::tcp::socket socket_;
    char* msg_data;

    void handle_connect(const boost::system::error_code& error);
    void handle_read(const boost::system::error_code& error);

};

[ Voor 70% gewijzigd door xehbit op 25-08-2011 21:31 ]


Acties:
  • 0 Henk 'm!

  • cpt.spiff
  • Registratie: Augustus 2009
  • Laatst online: 20-02 14:29
Op r19 declareer je een member van het type boost::asio::ip::tcp::socket. Dit is een typedef voor boost::asio::basic_stream_socket<boost::asio::ip::tcp>.

basic_stream_socket heeft geen "nullary constructor", met andere woorden: wanneer je een socket wilt construeren moet je op z'n minst 1 constructor-argument meegeven: een io_service, of een ander socket object in het geval van een copy constructor.

Je class tcpClient declareert geen constructors, dus krijg je een default constructor van de compiler. Deze probeert echter je members te construeren zonder argumenten en dat gaat dus mis op je socket_ member.

De compiler kiest er voor om deze melding op r13--het begin van je classdefinitie--te tonen, omdat er geen echte aanwijsbare code is voor de door de compiler gegenereerde default constructor.

In het kort: geef je tcpClient class een constructor die aan je socket een io_service meegeeft en het zou moeten compileren.

Acties:
  • 0 Henk 'm!

  • xehbit
  • Registratie: Februari 2009
  • Laatst online: 26-08 22:19
cpt.spiff schreef op vrijdag 26 augustus 2011 @ 12:32:
Op r19 declareer je een member van het type boost::asio::ip::tcp::socket. Dit is een typedef voor boost::asio::basic_stream_socket<boost::asio::ip::tcp>.

basic_stream_socket heeft geen "nullary constructor", met andere woorden: wanneer je een socket wilt construeren moet je op z'n minst 1 constructor-argument meegeven: een io_service, of een ander socket object in het geval van een copy constructor.

Je class tcpClient declareert geen constructors, dus krijg je een default constructor van de compiler. Deze probeert echter je members te construeren zonder argumenten en dat gaat dus mis op je socket_ member.

De compiler kiest er voor om deze melding op r13--het begin van je classdefinitie--te tonen, omdat er geen echte aanwijsbare code is voor de door de compiler gegenereerde default constructor.

In het kort: geef je tcpClient class een constructor die aan je socket een io_service meegeeft en het zou moeten compileren.
Okay, constructor gemaakt voor de tcpClient class:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#pragma once

#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>

using boost::asio::ip::tcp;

class tcpClient
{

public:
    tcpClient(boost::asio::io_service& io_service):
        socket_(io_service)
    {

    }


    bool Connect(char* host, int port);

private:
    boost::asio::ip::tcp::socket socket_;
    char* msg_data;

    void handle_connect(const boost::system::error_code& error);
    void handle_read(const boost::system::error_code& error);

};


Alleen wanneer ik dus in de main(); een pointer maak voor de tcpClient moet ik gebruik maken van boost::asio::io_service. Dit is iets wat ik eigenlijk niet wil doen. Vandaar de class tcpClient.

C++:
1
2
3
4
5
6
7
8
int main()
{
    boost::asio::io_service io_service;
    tcpClient *client = new tcpClient(io_service);

    client->Connect("localhost", 5005);
    return 0;
}


Zou het ook kunnen zonder in de main(); een io_service aan te maken. Dat dit allemaal in de class zelf gebeurd ?

Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15:26
Je kunt members in je constructor initialiseren:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
class tcpClient
{

public:
    tcpClient() : io_service(), socket_(io_service)
    {

    }

private:
    boost::asio::io_service io_service;
    boost::asio::ip::tcp::socket socket_;
};

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • cpt.spiff
  • Registratie: Augustus 2009
  • Laatst online: 20-02 14:29
Je kunt inderdaad een io_service als member van je tcpClient class declareren (die je trouwens niet expliciet hoeft te construeren, de constructie-volgorde wordt bepaald door de volgorde van declaratie in je class).

Meestal komt dat echter niet goed uit. Uit je members handle_connect en handle_read leid ik af dat je asynchrone communicatie wilt, en dan zul je toch op enig moment de run()-member van de io_service moeten aanroepen om alles te starten.

Kijk anders eens tussen de examples van boost.asio en kijk naar de source van een asynchrone client (b.v. de http client) http://www.boost.org/doc/.../boost_asio/examples.html.

Acties:
  • 0 Henk 'm!

  • xehbit
  • Registratie: Februari 2009
  • Laatst online: 26-08 22:19
cpt.spiff schreef op zaterdag 27 augustus 2011 @ 14:02:
Je kunt inderdaad een io_service als member van je tcpClient class declareren (die je trouwens niet expliciet hoeft te construeren, de constructie-volgorde wordt bepaald door de volgorde van declaratie in je class).
Aha, thanks. heb je hier meer informatie over? Misschien een linkje O-)
cpt.spiff schreef op zaterdag 27 augustus 2011 @ 14:02:
Meestal komt dat echter niet goed uit. Uit je members handle_connect en handle_read leid ik af dat je asynchrone communicatie wilt, en dan zul je toch op enig moment de run()-member van de io_service moeten aanroepen om alles te starten.
Dat heb je goed gezien ja, ik wil een class maken die het makkelijk maakt om een TCP/IP Stream op te zetten. Dus met makkelijke functies zoals connect(); disconnect(); isConnected(); onDataReceive(); onDataSend(); etc..
de run()-member wil ik dan ook uitvoeren onder de functie connect(), waar het ip en poort aan word door gegeven.
en bij de functie disconnect(); de io_service weer stoppen.
cpt.spiff schreef op zaterdag 27 augustus 2011 @ 14:02:
Kijk anders eens tussen de examples van boost.asio en kijk naar de source van een asynchrone client (b.v. de http client) http://www.boost.org/doc/.../boost_asio/examples.html.
Hier snap ik volgens mij iets niet helemaal, ik zie nergens dat er een poort word opgegeven. Zoals poort 80 zoals je in de http client demo bekijkt. Of zie ik iets anders over het hoofd ?

edit: Ah, ik zag inderdaad iets over het hoofd.
C++:
1
tcp::resolver::query query(server, "http");


de query(); is de 1e argument de host (mag dit ook een hostname zijn of moet dit een IPAddress zijn ?), en het 2e argument de poort. Hier staat http tussen quotes dus ik denk dat boost dat omzet naar 80 ?

[ Voor 11% gewijzigd door xehbit op 27-08-2011 18:02 ]


Acties:
  • 0 Henk 'm!

  • cpt.spiff
  • Registratie: Augustus 2009
  • Laatst online: 20-02 14:29
Dragon707 schreef op zaterdag 27 augustus 2011 @ 17:58:
[...]
Aha, thanks. heb je hier meer informatie over? Misschien een linkje O-)
[...]
De C++ standaard. [class.base.init], bijvoorbeeld in deze versie:
In a non-delegating constructor, initialization proceeds in the following order:
— First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in
the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes,
where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
— Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list
(regardless of the order of the mem-initializers).
— Then, non-static data members are initialized in the order they were declared in the class definition
(again regardless of the order of the mem-initializers).
— Finally, the compound-statement of the constructor body is executed.
C++:
1
tcp::resolver::query query(server, "http");


de query(); is de 1e argument de host (mag dit ook een hostname zijn of moet dit een IPAddress zijn ?), en het 2e argument de poort. Hier staat http tussen quotes dus ik denk dat boost dat omzet naar 80 ?
Uiteindelijk worden zowel de hostnames en service names door je OS/sockets API vertaald.
Pagina: 1