Forum: PC-Programmierung C/C++ Socket Programmierung


von Andreas W. (avedo)


Angehängte Dateien:

Lesenswert?

Guten Abend!

Ich beschäftige mich momentan mit Socket Programmierung in C. Dazu 
arbeite ich schrittweise die Seite 
http://www.zotteljedi.de/socket-tipps/index.html durch. Dort habe ich 
auch einen kleinen PortScanner in C gefunden, der mir recht gut gefallen 
hat, und so habe ich mir vorgenommen diesen in C++ nach zu 
programmieren.

Zu diesem Zweck habe ich eine Klasse TcpSocket geschrieben, die mir die 
Verbindung zu einem Server erleichtern soll. Eine Klasse SocketTest in 
der Datei Main.cpp implementiert darauf basierend den eigentlichen 
PortScanner.

Das Projekt kompiliert, liefert jedoch den Fehler, dass keine Verbindung 
aufgebaut werden kann. Der Fehler muss also in der Methode
1
bool TcpSocket::connectTo(std::string host, int port) throw(TcpSocketException);

liegen. In den betreffenden Zeilen
1
  if( connect(this->sock, (struct sockaddr*) &addr, sizeof(addr)) == -1 ) {
2
    // ... and handle errors.
3
      throw TcpSocketException("Failed to connect to " + host + ".");
4
  }

kann ich leider keinen Fehler finden. Mache ich vielleicht bei der 
Umrechnung der IP bzw. Host-Adresse etwas falsch? Wäre nett, wenn sich 
das jemand anschauen könnte.

Das Projekt habe ich als *.tar.gz angehängt. Bitte nicht über den Namen 
wundern.

Liebe Grüße,

Andreas

von duselbaer (Gast)


Lesenswert?

Hi,

ich habe mir den Beispielcode jetzt nicht angeschaut, würde Dir aber zum 
Thema Socketprogrammierung in C++ die Boost-Libs - insbesondere 
Boost.Asio - ans Herz legen.

Gruss,

RSp

von duselbaer (Gast)


Lesenswert?

achso, ansonsten setzt die connect-Funktion für gewöhnlich einen 
Errorcode in der Variable errno. Manchmal hilft es, diesen auszuwerten. 
Vielleicht kannst Du da was erkennen.

von Marco (Gast)


Lesenswert?

errno (unter Windows WSAGetLastError) auszugeben sollte weiterhelfen, 
den Fehler einzugrenzen.

von Andreas W. (avedo)


Lesenswert?

Hallo!

Danke für deine Antwort. Werde mir die Boost-Library auf jeden Fall mal 
ansehen.

Der Fehler scheint im übrigen nur dann aufzutauchen, wenn ich eine 
Host-Adresse (URL) entgegen nehme. Kann es sein, dass ich etwas bei der 
Umwandlung falsch mache?

Nachfolgend mal der betreffende Code-Ausschnitt.
1
  // Check if given host address is an ip.
2
  if( inet_aton(host.c_str(), &addr.sin_addr) == 0 ) {
3
    // If not get data by hostname ...
4
    hostData = gethostbyname(host.c_str());
5
    
6
    // Validate host data ...
7
    if (!hostData) {
8
      // ... and handle errors.
9
      throw TcpSocketException("Failed to resolve " + host + ".");
10
    }
11
    
12
    // Finally set host address.
13
    addr.sin_addr = *(struct in_addr*) hostData->h_addr;
14
  }
15
  
16
  else {
17
    // If ip was given set host address by ip.
18
    addr.sin_addr.s_addr = inet_addr(host.c_str());
19
  }
20
21
  // Init address structure.
22
  addr.sin_port = htons(port);
23
  addr.sin_family = AF_INET;
24
25
  // Establish connection to given ip address and port ...
26
  if( connect(this->sock, (struct sockaddr*) &addr, sizeof(addr)) == -1 ) {
27
    // ... and handle errors.
28
      throw TcpSocketException("Failed to connect to " + host + ".");
29
  }
30
31
  return true;

Liebe Grüße,

Andreas

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Andreas Wilhelm schrieb:
> Der Fehler scheint im übrigen nur dann aufzutauchen, wenn ich eine
> Host-Adresse (URL) entgegen nehme.
Eine URL kannst du nicht angeben. "mikrocontroller.net", 
"www.mikrocontroller.net" sollte funktionieren, aber 
"http://mikrocontroller.net"; ist zwar eine URL aber kein gültiger 
Hostname!

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

In Zeile 12:
1
sock = socket(PF_INET, SOCK_STREAM, 0);
Man soll angeblich korrekt AF_INET schreiben, aber das ist wohl 
praktisch immer egal.

von Karl H. (kbuchegg)


Lesenswert?

Andreas Wilhelm schrieb:

> Der Fehler scheint im übrigen nur dann aufzutauchen, wenn ich eine
> Host-Adresse (URL) entgegen nehme. Kann es sein, dass ich etwas bei der
> Umwandlung falsch mache?


Sein kann alles.
Hast du denn keinen Debugger, mit dem du den Code in Einzelschritten 
durchgehen kannst? Oder eine Ausgabefläche (Monitor, Textfenster) in das 
du Fehlermeldungen samt Parameter bzw. ganz einfache Log-Meldungen ala 
'Now trying to resolve Host-Name' ausgeben kannst und zwar an der Stelle 
bzw. bevor der Fehler gethrowd wird?

von Andreas W. (avedo)


Angehängte Dateien:

Lesenswert?

Guten Abend!

Karl heinz Buchegger schrieb:
> Hast du denn keinen Debugger, mit dem du den Code in Einzelschritten
> durchgehen kannst? Oder eine Ausgabefläche (Monitor, Textfenster) in das
> du Fehlermeldungen samt Parameter bzw. ganz einfache Log-Meldungen ala
> 'Now trying to resolve Host-Name' ausgeben kannst und zwar an der Stelle
> bzw. bevor der Fehler gethrowd wird?

Normalerweise arbeite ich ja mit dem QtCreator. Der hat 
selbstverständlich einen Debugger. Leider bin ich momentan mit meinem 10 
Zoll Netbook auf reisen auf dessen Display leider kein Platz für diese 
IDE ist. Natürlich habe ich versucht mit Log-Meldungen dahinter zu 
kommen, aber irgenetwas ging da schief.

duselbaer schrieb:
> Ich habe mir den Beispielcode jetzt nicht angeschaut, würde Dir aber zum
> Thema Socketprogrammierung in C++ die Boost-Libs - insbesondere
> Boost.Asio - ans Herz legen.

Ich habe mir die entsprechenden Bibliotheken heute mal angeschaut und 
etwas damit rumgespielt. Ich habe nun den PortScanner auf Basis der 
Boost Bibliotheken noch einmal neu geschrieben und stehe nun noch vor 
einem Problem. Ich habe in der Doku keine Möglichkeit gefunden anhand 
eines Ports den Namen des dazugehörigen Services auszugeben. Gibt es 
dafür irgendeine Funktion?

Außerdem ist das Programm momentan noch sehr langsam. Gibt es irgendeine 
Möglichkeit das ganze etwas zu beschleunigen?

Abschließend würde mich noch interessieren, ob man das so programmieren 
kann. Habe schon oft in Java, MatLab, C oder PHP programmiert, jedoch 
recht selten in C++.

Liebe Grüße,

Andreas

PS: Den PortScanner findet ihr im Anhang.

von Klaus W. (mfgkw)


Lesenswert?

Andreas Wilhelm schrieb:
> Ich habe in der Doku keine Möglichkeit gefunden anhand
> eines Ports den Namen des dazugehörigen Services auszugeben. Gibt es
> dafür irgendeine Funktion?

Zumindest unter Unix/Linux steht das in /etc/services, falls dir
nicht eleganteres über den Weg läuft.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Klaus Wachtler schrieb:
> Zumindest unter Unix/Linux steht das in /etc/services, falls dir
> nicht eleganteres über den Weg läuft.
Dabei brauchst du sie aber nicht von Hand parsen, Linux hat dafür 
Funktionen:
http://linux.die.net/man/5/services

von Andreas W. (avedo)


Lesenswert?

Guten Abend!

Niklas Gürtler schrieb:
> Klaus Wachtler schrieb:
> Dabei brauchst du sie aber nicht von Hand parsen, Linux hat dafür
> Funktionen:
> http://linux.die.net/man/5/services

Wenn ich das richtig sehe, habe ich genau das in meiner ersten Version 
gemacht. Wieso sollte man dann die Boost Bibliotheken verwenden. Welchen 
wirklich Vorteil bieten sie? Ich habe mich bisher nur darüber geärgert, 
dass man einen Port nur als String übergeben kann. Das verschließt sich 
mir jeglicher Logik.

Liebe Grüße,

Andreas

von Klaus W. (mfgkw)


Lesenswert?

Andreas Wilhelm schrieb:
> Wieso sollte man dann die Boost Bibliotheken verwenden.

Falls das eine Frage ist: weil das Programm dadurch auch unter
Windows oder sonstwo übersetzbar ist, wo es die boost-Lib gibt..

von Andreas W. (avedo)


Lesenswert?

Klaus Wachtler schrieb:
> Falls das eine Frage ist: weil das Programm dadurch auch unter
> Windows oder sonstwo übersetzbar ist, wo es die boost-Lib gibt..

Das gilt aber nicht mehr, sollte ich die Sockets, wie oben 
vorgeschlagen, abfragen.

Liebe Grüße,

Andreas

von Bob der Baumeister (Gast)


Lesenswert?

Andreas Wilhelm schrieb:
> Das gilt aber nicht mehr, sollte ich die Sockets, wie oben
> vorgeschlagen, abfragen.

Was wiederrum der Grund ist, warum dir die Boost-Lib vorgeschlagen 
wurde.

Wenn dir Boost nicht zusagt, aber die QT: Da gibts doch auch schöne 
QSocket Klassen usw. Die lassen sich auch ohne GUI verwenden.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.