Socket BIND schlägt fehl
-
Guten Tag,
baue grade an einer Socket-Verbindung...
Wenn ich (struct sockaddr*) weglasse, kommt es zu einem Compiler-Fehler:
daemon.cpp:30: error: invalid cast from type ‘sockaddr_in’ to type ‘sockaddr*’
Wenn ich die es mit (struct sockaddr*) kompiliere kommt es zu keinem compiler bedingten fehler. Jedoch zu "Failed to bind socket!"...perror funktioniert offensichtlich auch nicht richtig, wenn ich es nutze kommt es ebenfalls zu kompiler fehlern
OS: Ubuntu 10.04
Compiler: G++#include <iostream> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> using namespace std; main() { // Socket initialisieren int Socket; Socket = socket(AF_INET, SOCK_STREAM, 0); if(Socket == -1) { cout << "Failed to create socket!" << endl; return 1; } else { cout << "Created socket." << endl; } // Socket binden struct sockaddr_in Adresse; Adresse.sin_addr.s_addr = inet_addr("192.168.245.212"); Adresse.sin_port = htons(88); Adresse.sin_family = AF_INET; if(bind(Socket, (struct sockaddr*)&Adresse, sizeof(Adresse)) == -1) { cout << "Failed to bind socket!" << endl; return 2; } else { cout << "Bound socket." << endl; } // Am Socket horchen if(listen(Socket, 3) == -1) { cout << "Failed to listen on socket!" << endl; return 3; } else { cout << "Listen on socket." << endl; } }
-
struct sockaddr_in Adresse; memset(Adresse, 0, sizeof(sockaddr_in); // ...
Probier das mal und außerdem musst du dich entscheiden:
Programmierst du einen Server oder einen Client.Bei einem Server muss es heißen:
Adresse.sin_addr.s_addr=ADDR_ANY;
Und bei einem Client ist bind nicht notwendig, sondern connect.
Du solltest dir die Grundlagen nochmal ansehen.
-
> Du solltest dir die Grundlagen nochmal ansehen.
Du auch.
Code korrigiert:sockaddr_in Adresse; std::memset(&Adresse, 0, sizeof(sockaddr_in)); // ...
> Bei einem Server muss es heißen:
> Adresse.sin_addr.s_addr=ADDR_ANY;Ne, wenn schon muss es da heißen:
Adresse.sin_addr.s_addr = htonl(ADDR_ANY); // Byte-Order beachten!
@ TE: Unbedingt
errno
ausgeben lassen! Und kein reudiges C/C++ programmieren!C oder C++!
-
Ad aCTa schrieb:
> Du solltest dir die Grundlagen nochmal ansehen.
Du auch.
Code korrigiert:sockaddr_in Adresse; std::memset(&Adresse, 0, sizeof(sockaddr_in)); // ...
> Bei einem Server muss es heißen:
> Adresse.sin_addr.s_addr=ADDR_ANY;Ne, wenn schon muss es da heißen:
Adresse.sin_addr.s_addr = htonl(ADDR_ANY); // Byte-Order beachten!
@ TE: Unbedingt
errno
ausgeben lassen! Und kein reudiges C/C++ programmieren!C oder C++!
Lehn dich mal nicht zu weit aus dem Fenster. Es handelt sich um winzige Fehler, schließlich habe ich nicht die Zeit, dass ich eine Garantie für 100% Richtigkeit geben kann. Ich helfe schließlich freiwillig in meiner privaten Zeit. Ich hätte auf Nachfragen des OP meinen Fehler gesehen und korrigiert.
Und spätestens mit deiner zweiten Aussage hast du gezeigt, dass du keine Ahnung hast. Die Byte Order ist in diesem Fall nämlich nicht notwendig. Der Rest meines Codes, inklusive ADDR_ANY (ohne htonl!) ist so vollkommen korrekt.
-
Das Ding heißt INADDR_ANY und muss nicht zwangsläufig bei einem Server angegeben werden - wenn das Binden an ein bestimmtes Netzwerkinterface gewünscht ist, ist die Angabe einer IP-Adresse vollkommen in Ordnung.
Ich denke das Problem ist hier, dass Port 88 "privileged" ist und als solcher nur Root zur Verfügung steht.
-
Geselle ich mich mal dazu
Port 0 - 1023, well-know ports (sollten nicht verwendet werden)
Port 1024 - 49151 registered ports (dienen primär der initalen Kontaktaufnahme)
Port 49152 - 65535 dynamic ports (frei zu nutzen)Such mal nach den Begriffen wenn du mehr darüber wissen willst, aber für eigene Anwendungen sollten man sich im Bereich > 1024 aufhalten, für den Datenaustausch dann >49151
htonl() ist sicherlich nicht notwendig, wenn man mit Systemen arbeitet, die die gleiche Endian-Aufteilung nutzen, aber es vorzusehen und htonl() prämetiv zu nutzen, erspart einem Ärger wenn man dann doch mal in die Situation kommt, wo BigEndian-System mit LittleEndian-System reden will.
-
LordJaxom schrieb:
Ich denke das Problem ist hier, dass Port 88 "privileged" ist und als solcher nur Root zur Verfügung steht.
Damn du hast Recht.Auf die Idee bin ich echt nicht gekommen, aber als root geht es.
Danke Danke
Seid lieb zueinander
-
Zooom schrieb:
Geselle ich mich mal dazu
Port 0 - 1023, well-know ports (sollten nicht verwendet werden)
Port 1024 - 49151 registered ports (dienen primär der initalen Kontaktaufnahme)
Port 49152 - 65535 dynamic ports (frei zu nutzen)Such mal nach den Begriffen wenn du mehr darüber wissen willst, aber für eigene Anwendungen sollten man sich im Bereich > 1024 aufhalten, für den Datenaustausch dann >49151
htonl() ist sicherlich nicht notwendig, wenn man mit Systemen arbeitet, die die gleiche Endian-Aufteilung nutzen, aber es vorzusehen und htonl() prämetiv zu nutzen, erspart einem Ärger wenn man dann doch mal in die Situation kommt, wo BigEndian-System mit LittleEndian-System reden will.
INADDR_ANY ist aber bereits vordefiniert und wird nicht über die Leitung versendet, daher braucht man das nicht.
Beim Senden von Daten ist die Endianess natürlich zu beachten.
-
ghjghj schrieb:
INADDR_ANY ist aber bereits vordefiniert und wird nicht über die Leitung versendet, daher braucht man das nicht.
Beim Senden von Daten ist die Endianess natürlich zu beachten.Auch der Rückgabewert von inet_addr hat bereits korrekte Byte-Order. Beim Befüllen der Struktur sockaddr_in braucht man daher i.A. nur htons für den Port.
-
LordJaxom schrieb:
ghjghj schrieb:
INADDR_ANY ist aber bereits vordefiniert und wird nicht über die Leitung versendet, daher braucht man das nicht.
Beim Senden von Daten ist die Endianess natürlich zu beachten.Auch der Rückgabewert von inet_addr hat bereits korrekte Byte-Order. Beim Befüllen der Struktur sockaddr_in braucht man daher i.A. nur htons für den Port.
Ich habe nie etwas gegenteiliges behauptet. Mit dem Senden von Daten meinte ich:
send(...)
Dort muss man je nach Zielsystem(en) und Datentypen entsprechend aufpassen.