[C++] Bij verbinden van TCP client loop gehele console vast.

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

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

Laatst heb ik een programma geschreven waarmee ik via een Console TCP verbindingen kan maken, Alleen wanneer ik wil verbinden loopt de gehele console vast. Ik zat aan een oplossing te denken om een thread te starten wanneer er een verbinding moet worden gemaakt. Maar is dit dan wel goed te doen of zeggen jullie dat het dan maar beter is om eventjes te wachten totdat de verbinding tot stand is gebracht.

Wat raden jullie aan om voor methode te kiezen om dit probleem te kunnen voorkomen ?

Acties:
  • 0 Henk 'm!

  • Radiant
  • Registratie: Juli 2003
  • Niet online

Radiant

Certified MS Bob Administrator

Threads, zoals je zelf zegt, of non-blocking sockets..

Acties:
  • 0 Henk 'm!

  • xehbit
  • Registratie: Februari 2009
  • Laatst online: 26-08 22:19
Radiant schreef op dinsdag 27 december 2011 @ 14:30:
Threads, zoals je zelf zegt, of non-blocking sockets..
Oke, ik heb eerder al eens een stukje code geschreven voor threaded sockets zie:
http://code.google.com/p/...ession/networksession.cpp

Maar is dat ook een beetje in orde om het op deze manier te doen ?

Acties:
  • 0 Henk 'm!

  • Radiant
  • Registratie: Juli 2003
  • Niet online

Radiant

Certified MS Bob Administrator

Tja, wat heet "in orde" ;)

Non-blocking sockets zijn vaak al snel een vereiste, ook bij threading, als je met timeouts e.d. wil gaan werken (even afhankelijk van de mogelijkheden van je socket API). Threading brengt een hoop complexiteit met zich mee in de vorm van locking, signalling naar je console thread, enzovoort.

Het hangt nogal behoorlijk van je toepassing af.. Als je alleen simpel een console applicatietje wil en je wil dat achter het woord "Connecting.." er elke seconde een extra puntje verschijnt of als je een timeout op de verbindpoging wil zou ik lekker de threads achterwege laten en enkel met non-blocking sockets werken en een wachtlusje.
Als je echter een high performance HTTP server wil gaan maken voor machines met veel cores waar de threads onderling weinig tot geen interactie zouden hebben zou ik er ook wat threads tegenaan gooien.

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Ik zou ook (als dat kan/mag) kijken naar iets als Qt ( http://doc.qt.nokia.com/4.7-snapshot/qtnetwork.html ) ipv zelf ruwe sockets te gaan programmeren.

Acties:
  • 0 Henk 'm!

  • Styxxy
  • Registratie: Augustus 2009
  • Laatst online: 20-09 19:45
Zoijar schreef op dinsdag 27 december 2011 @ 15:00:
Ik zou ook (als dat kan/mag) kijken naar iets als Qt ( http://doc.qt.nokia.com/4.7-snapshot/qtnetwork.html ) ipv zelf ruwe sockets te gaan programmeren.
Of Boost.Asio gebruiken (al is Qt waarschijnlijk wel gemakkelijker).

Acties:
  • 0 Henk 'm!

  • eppie
  • Registratie: Maart 2000
  • Niet online
(overleden)
Ik ben zelf wel gecharmeerd van de library Poco en daarvan de TCPServer classes.
http://www.appinf.com/docs/poco/Poco.Net.TCPServer.html

Erg makkelijk in gebruik.

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Ik heb het alle drie in het verleden gebruikt, en vond Qt toch het makkelijkste/beste. Asio is vrij low-level en ingewikkeld (boost clutter), en Poco... tsaj, weer zo'n heel framework installen, en het werkte niet allemaal helemaal lekker, of was nog in beta... ik was er niet zo weg van. Voordeel van Qt was voor mij toch ook wel dat ik toch een ui moest hebben en de directe link met WebKit.

  • xehbit
  • Registratie: Februari 2009
  • Laatst online: 26-08 22:19
Eigenlijk is het toch wel mijn doel om met RAW sockets te gaan werken. Maar veel handleidingen (bijv; beej's guide) word wel uitgelegd hoe je met die sockets werkt. Alleen niet dat je alles in een thread kan stoppen etc..

Het is eigenlijk niet veel meer dan een soort telnet client.

  • leuk_he
  • Registratie: Augustus 2000
  • Laatst online: 15-07 15:35

leuk_he

1. Controleer de kabel!

Voor een client zou je alle communicatie (niet alleen connectie maken) in een thread kunnen doen. Als je echter in wil kunnen grijpen vanuit de (console ...) gui, dan kom je toch weer op non blocking io. Je wil dat overigens voor ALLE communicatie doen, niet alleen voor de connect. Immers alle calls kunnen blokken als de server er even niet is, of als de verbindng even wegvalt.

Voor server applicaties kost 1 thread per connectie meestal te veel server resources (java mensen, herken je dit?) , dus daar ga je andere methoden gebruiken.

Need more data. We want your specs. Ik ben ook maar dom. anders: forum, ff reggen, ff topic maken
En als je een oplossing hebt gevonden laat het ook ujb ff in dit topic horen.


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15:26
leuk_he schreef op donderdag 29 december 2011 @ 12:52:
Voor server applicaties kost 1 thread per connectie meestal te veel server resources (java mensen, herken je dit?) , dus daar ga je andere methoden gebruiken.
Geldt niet alleen voor Java hoor, ook in C bijv is het gebruikelijk om meerdere clients af te handelen met select(...) of vergelijkbare calls : een thread per client was en is behoorlijk resource intensief.

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.


  • xehbit
  • Registratie: Februari 2009
  • Laatst online: 26-08 22:19
Maar wanneer je dat niet doet, voor elke client een aparte thread kan je gehele programma vastlopen toch door blocking ?

  • Radiant
  • Registratie: Juli 2003
  • Niet online

Radiant

Certified MS Bob Administrator

Daar hebben ze dus non-blocking sockets voor uitgevonden..

  • xehbit
  • Registratie: Februari 2009
  • Laatst online: 26-08 22:19
Radiant schreef op donderdag 29 december 2011 @ 13:35:
Daar hebben ze dus non-blocking sockets voor uitgevonden..
Daar heb ik inderdaad veel over gelezen. Is er ook een documentatie waar het verschil tussen blocking en non-blocking goed word uitgelegd. Ikzelf heb deze al gevonden maar zou graag wat meer van dit soort documentaties willen vinden.

  • Radiant
  • Registratie: Juli 2003
  • Niet online

Radiant

Certified MS Bob Administrator

Als je zoekt op "winsock non blocking" kom je vrij veel tegen.. Het werkt grotendeels hetzelfde, je moet alleen met ioctlsocket() even je sockets als non-blocking markeren. Daarna returnen je send(), recv(), connect(), etc functies meteen ipv. dat ze blocken en moet je met select() gaan kijken wat de staat van je sockets is.

  • leuk_he
  • Registratie: Augustus 2000
  • Laatst online: 15-07 15:35

leuk_he

1. Controleer de kabel!

Dragon707 schreef op donderdag 29 december 2011 @ 13:33:
Maar wanneer je dat niet doet, voor elke client een aparte thread kan je gehele programma vastlopen toch door blocking ?
Alleen de thread die communicatie doet blockt.

Dus je gui (main) thread loopt dan door. Je kunt echter vanaf je gui de communicatie thread niet afbreken als deze aan het blokkeren is.(kan wel... maar de essentie is dus dat je dan weer verantwoording schuift naar je hoofd thread...) Dus dan heb je het probleem van de connect naar de (nette...) disconnect verschoven. Tenzij een nette disconnect niet van belang is.

[ Voor 8% gewijzigd door leuk_he op 29-12-2011 14:01 ]

Need more data. We want your specs. Ik ben ook maar dom. anders: forum, ff reggen, ff topic maken
En als je een oplossing hebt gevonden laat het ook ujb ff in dit topic horen.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

leuk_he schreef op donderdag 29 december 2011 @ 12:52:
Voor server applicaties kost 1 thread per connectie meestal te veel server resources (java mensen, herken je dit?) , dus daar ga je andere methoden gebruiken.
Daar is boost.Asio dan weer erg goed in. Veel connecties uit een thread door een async callback model.

Ik zou dus nooit raw sockets gaan programmeren als je goede, snelle, platform-onafhankelijke libraries beschikbaar hebt. Als het gewoon met boost.asio bouwt werkt het ook meteen onder linux en windows. Verder zit je eigenlijk net zo dicht op je sockets.

Hier, een chat client, bijna hetzelfde als telnet: http://www.boost.org/doc/...mple/chat/chat_client.cpp

[ Voor 34% gewijzigd door Zoijar op 29-12-2011 14:13 ]


  • xehbit
  • Registratie: Februari 2009
  • Laatst online: 26-08 22:19
Zoijar schreef op donderdag 29 december 2011 @ 14:08:
[...]

Daar is boost.Asio dan weer erg goed in. Veel connecties uit een thread door een async callback model.

Ik zou dus nooit raw sockets gaan programmeren als je goede, snelle, platform-onafhankelijke libraries beschikbaar hebt. Als het gewoon met boost.asio bouwt werkt het ook meteen onder linux en windows. Verder zit je eigenlijk net zo dicht op je sockets.

Hier, een chat client, bijna hetzelfde als telnet: http://www.boost.org/doc/...mple/chat/chat_client.cpp
Ik zit er inderdaad over te denken om het alsnog via Boost.Asio te gaan doen. Maar zijn raw sockets wel sneller dan de ASIO van boost ? Of maakt dat helemaal niks uit?

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15:26
Waarschijnlijk ga je qua snelheid niet snel tegen limitieten oplopen, en al helemaal gaat het snelheidsverschil tussen "plain sockets" ( raw sockets zijn iets anders ) en boost.asio niet het verschil maken.

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.


  • xehbit
  • Registratie: Februari 2009
  • Laatst online: 26-08 22:19
farlane schreef op donderdag 29 december 2011 @ 21:14:
Waarschijnlijk ga je qua snelheid niet snel tegen limitieten oplopen, en al helemaal gaat het snelheidsverschil tussen "plain sockets" ( raw sockets zijn iets anders ) en boost.asio niet het verschil maken.
Dat heb ik inderdaad door elkaar gehaald. Ik heb een test gemaakt om toch een manier te vinden om er voor te zorgen dat ik niet al te veel last heb van blocking.

Helaas krijg ik mijn testcase niet helemaal werkend. Ik verwacht "VER 1 MSNP21" als terug keerend commando. Maar ik ontvang niets vreemd genoeg.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include <string>
#include <windows.h>
#include <WinSock2.h>

using namespace std;

SOCKET sck;

void sckConnect(string host, unsigned short port);
void sendCommand(string cmd);
void recieveCommand(char* buffer, int size);

int main()
{
    cout << "Blocking Sockets Test." << endl << endl;

    char* buf = '\0';

    for(unsigned long ticks=0; ; ticks++)
    {
        cout << ticks << "\r";
        if(ticks == 5000) sckConnect("SERVERIP", 1863);
        if(ticks == 10000) sendCommand("VER 1 MSNP21 MSNP20 MSNP19 MSNP18 MSNP17 CVR0");
        if(ticks == 15000) recieveCommand(buf, 10);
        if((ticks % 200) == true) Sleep(1);
    }
    return 0;
}

void sckConnect(string host, unsigned short port)
{
    WSADATA wsa;
    if(WSAStartup(MAKEWORD(2,0), &wsa))
    {
        throw "Could not startup WSA...";
    }

    sck = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(sck == INVALID_SOCKET)
    {
        throw "Could not create a valid socket...";
    }

    sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.S_un.S_addr = inet_addr(host.c_str());
    address.sin_port = htons(port);
    connect(sck, (sockaddr *)&address, sizeof(address));

    int err = WSAGetLastError();
    if(err == 10060)
    {
        //throw "Could not connect, it seems that the server is offline.";
        cout << "It seems that the server is offline !";
    }
    else if(err != 0)
    {
        //throw "Could not connect, it seems that the server is offline.";
        cout << "Unknown error ! :"<<err;
    }


    unsigned long BlockingMode = 0;
    ioctlsocket(sck, FIONBIO, &BlockingMode);

    cout<<endl<<"Successfully established connection !"<<endl;
}

void sendCommand(string cmd)
{
    string parsecmd = cmd + "\r\n";
    send(sck, parsecmd.c_str(), strlen(parsecmd.c_str()), 0);
    cout<<endl<<"Successfully send command: "<<cmd<<endl;
}

void recieveCommand(char* buffer, int size)
{
    int i = recv(sck, buffer, size, 0);
    cout<<endl<<"Successfully recieved command: "<<buffer<<" (size: "<<i<<")"<<endl;
}

Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Niet je hele code doorgefietst, maar iets wat me opvalt:
Dragon707 schreef op donderdag 29 december 2011 @ 22:01:

C++:
1
2
3
char* buf = '\0';
// <SNIP>
if(ticks == 15000) recieveCommand(buf, 10);
Dat gaat natuurlijk niet werken ;)

hint:

C++:
1
2
3
char buf[BUF_SIZE + 1] = {0};

if(ticks == 15000) recieveCommand(buf, BUF_SIZE);

Acties:
  • 0 Henk 'm!

  • xehbit
  • Registratie: Februari 2009
  • Laatst online: 26-08 22:19
EddoH schreef op vrijdag 30 december 2011 @ 12:15:
Niet je hele code doorgefietst, maar iets wat me opvalt:


[...]


Dat gaat natuurlijk niet werken ;)

hint:

C++:
1
2
3
char buf[BUF_SIZE + 1] = {0};

if(ticks == 15000) recieveCommand(buf, BUF_SIZE);
Je bent geweldig! Het probleem is hierdoor opgelost.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Maar weet je ook waarom?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • xehbit
  • Registratie: Februari 2009
  • Laatst online: 26-08 22:19
Jazeker, nouja dat hoop ik van wel.

C++:
1
char* buf = '\0'; 

Eindigt op de nulbyte "\0" waardoor er niks in gezet kan worden right ?

Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 10:43

Matis

Rubber Rocket

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

En dat is nou het jammere van kant en klare oplossingen in posts ;)

In die regel code zitten 3 dingen die je waarschijnlijk niet verwacht (en ik vermoed dat de meeste hier een van die dingen ook niet zien)
C++:
1
char* buf = '\0';

Ten eerste definieer je een pointer naar char genaamd 'buf' die je verwijst naar een string (niet helemaal, dat komt in puntje 3, maar bear with me ;)). Die string staat in feite in "constant memory" en mag je helemaal niet wijzigen. Het feit dat je een string literal mag assignen aan een niet-const char* is een erfenis van C, maar eigenlijk is een string literal een const char[] en dus is een verwijzing daarnaar ook een const char *.

Dat brengt ons naar punt 2, je mag de buffer niet aanpassen. Het is sowieso geen buffer, de string is slechts zo lang als de literal, met aan het einde een \0 character. Je kunt 'm dus ook niet gebruiken om eigen dingen erin te zetten. Je moet dus echt een array van een bepaalde definieren (of alloceren) die je aan mag passen. Alternatieven zijn:
C++:
1
2
char buf1[100];  // buffer lokaal aan de huidige functie
char * buf2 = new char[100]; // buffer op de heap, niet vergeten delete[] erop aan te roepen als je ermee klaar bent

Een std::string encapsuleert in feite een string op de heap, en doet alle memory management voor jou, met het nadeel dat je er eigenlijk niet direct naar mag schrijven. Een std::vector<char> is dan wellicht een betere optie - het is gegarandeerd dat alle elementen van de vector sequentieel in geheugen staan. Je mag dus het adres van het eerste element opvragen en behandelen als array.

En dan nu het derde punt, waarvan ik vermoed dat iedereen daar overheen heeft gekeken: je initialiseert 'buf' helemaal niet met een string literal, maar met een character literal. Feitelijk mag dat helemaal niet (je kunt een char immers niet casten naar een char*), maar omdat het in dit geval het nul character literal is, is het hetzelfde als:
C++:
1
char * buf = 0;

Oftewel, je initialiseert 'buf' met een null pointer.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Mijn excuses voor het gebrek aan uitleg bij mijn post en dank aan .oisyn voor die uitleg :+


....Ik lag met m'n kont in het zwembad 8)
Pagina: 1