Frage zu Socket-Programmierung und select()
-
Hab ich schon. Guck mal oben im Code, hab da einen Kommentar drin. An der Stelle wo n -1 wird bricht das Programm ab und der Fehler kommt
-
Den Grund (ich nehme mal an, dass das der Grund ist) dafür habe ich dir bereits in meinem ersten Post genannt. Oder hast du das schon ausprobiert?
-
Ja, ich hab das FD_ZERO schon getestet. Der Fehler bleibt leider der gleiche
-
Dann bau mal ein
printf ("%s %d\n", strerror (errno), errno);mit vorherigem#include <errno.h>ein und schau nach, was der Fehler bedeutet bedeutet. (Oder wird das unter Windows mitWSAGetLastError ();gemacht?)
-
printf ("%s %d\n", strerror (errno), WSAGetLastError());Da gibt er folgendes aus:
No Error 10038
-
http://msdn.microsoft.com/en-us/library/ms740668(VS.85).aspx schrieb:
WSAENOTSOCK
10038Socket operation on nonsocket.
An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket, or for select, a member of an fd_set was not valid.Dann hat der Client irgendwie die Verbindung abgebrochen oder der Socket ist im Server put gegangen. Kann jetzt auf den ersten Blick den Grund auch nicht erkennen...
-
Ja genau. Hilft es vl wenn ich den Code vom Client auch noch poste?
// RN_P_Beispielclient.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung. // #include "stdafx.h" #include <winsock.h> #include <iostream> #include <conio.h> #include <io.h> #define PROTOPORT 5000 // Default Portnummer #define AF_INET_LEN 4 // Länge IPv4-Adresse in Byte using namespace std; int main(int argc, char* argv[]) { //-------------------------------------------------------------------------------------- // Program: RN_P_Beispielclient.cpp // // Funktion: Baut eine TCP-Verbindung zu einem Server auf, gibt dessen Nachricht // auf dem Bildschirm aus und bestätigt die Verbindung. // // Aufruf: RN_P_Beispielclient [<Rechnername>][<Portnummer>] // <Rechnername>: Rechnername des Servers // <Portnummer>: Portnummer unter welcher der Server seinen // Dienst anbietet // // Bemerkung: Die Eingabe der Parameter ist optional. Falls kein Rechnername // spezifiziert ist, verwendet der Client "localhost" (127.0.0.1); // falls kein Port spezifiziert ist, wird der durch PROTOPORT definierte // Default-Wert verwendet! // // Dr. W. Schmitt, 02.05.08 //-------------------------------------------------------------------------------------- const char *Datum = "02.05.08"; int Fehlerkode; // Hilfsvariable zum Speichern eines Fehlerkodes char localhost[] = "localhost"; // Default Hostname hostent *ptrh; // Speichert den Namen des Clientrechners protoent *ptrp; // Speichert den Namen des Transp.Protok. sockaddr_in serveradress; // Speichert die Serveradresse SOCKET sock; // Socket Descriptor unsigned short port; // Portnummer des Servers char *host; // Host Name static_cast<void*> unsigned int n; // Anzahl empfangener Bytes char RecvBuf[100]; // Puffer für Empfangsdaten char SendBuf[100]; // Puffer für Sendedaten char *SendeText = "TCP-Verbindungsaufbau erfolgreich! \n"; WSADATA wsaData; // Speichert Winsock-Initialisierungsinfo WORD wVersionRequested; // Speichert die gewünschte Version der Winsock- // DLL wVersionRequested = MAKEWORD(2, 2); // Initialisierung der Winsock-DLL Fehlerkode = WSAStartup(wVersionRequested, &wsaData); if (Fehlerkode != NO_ERROR) { fprintf_s(stdout,"Initialisierung der Winsock-DLL fehlgeschlagen: %i\n", Fehlerkode); } // Bildschirmausgabe einer Begrüßungsnachricht fprintf_s(stdout, "Hallo Client!\n"); memset(&serveradress, 0, sizeof(serveradress)); // Initialisiere sad mit 0 serveradress.sin_family = AF_INET; // Setze "Internetadressierung" // Auswerten der Kommandozeilenparameter if (argc > 1) { // Falls <Rechnername> vorhanden // dann in host speichern host = argv[1]; } else { // sonst verwende "localhost" host = localhost; } ptrh = gethostbyname(host); // <Rechnername> --> IP-Adresse if (ptrh == NULL) { fprintf_s(stdout,"ungültige Rechneradresse: %s\n", host); WSACleanup(); exit(EXIT_FAILURE); } if (argc > 2) { // Falls <Portnummer> vorhanden // dann konvertiere nach int port = atoi(argv[2]); } else { // sonst verwende Default-Wert port = PROTOPORT; } if (port > 0) serveradress.sin_port = htons(port); // Host --> Netzwerk-Byteordnung else { // Drucke Fehlermeldung; Programmende fprintf_s(stdout,"Ungültige Portnummer %s\n",argv[2]); WSACleanup(); exit(EXIT_FAILURE); } if (memcpy_s(&serveradress.sin_addr, AF_INET_LEN, ptrh->h_addr, ptrh->h_length)) { fprintf_s(stdout,"Fehler beim Kopieren der Rechneradresse"); WSACleanup(); exit(EXIT_FAILURE); } if ((ptrp = getprotobyname("tcp")) == NULL) { // "tcp" --> Protokollcode fprintf_s(stdout, "Abbildung von \"tcp\" auf Protokollnummer nicht möglich!"); WSACleanup(); exit(EXIT_FAILURE); } // Erzeuge Socket sock = socket(PF_INET, SOCK_STREAM, ptrp->p_proto); if (sock == INVALID_SOCKET) { fprintf_s(stdout, "Fehler bei Generierung von Socket: %ld\n", WSAGetLastError()); WSACleanup(); exit(EXIT_FAILURE); } // Aktiver Verbindungsaufbau zum Server if (connect(sock, (struct sockaddr *)&serveradress, sizeof(serveradress)) == SOCKET_ERROR) { fprintf_s(stdout,"Fehler beim TCP-Verbindungsaufbau: %ld\n", WSAGetLastError()); WSACleanup(); exit(EXIT_FAILURE); } //solange du verbunden bist while(connect) { fprintf(stdout, "Bitte Nachricht eingeben:\n"); //Lese Text von der Konsole ein und schreibe in SendBuf cin.getline(SendBuf, 1000); send(sock, SendBuf,strlen(SendBuf),0); // Empfangene Daten lesen und auf dem Bildschirm schreiben // Daten aus TCP-Empfangspuffer lesen und in RecvBuf schreiben n = recv(sock, RecvBuf, static_cast<int>(strlen(RecvBuf)), 0); RecvBuf[n] = '\0'; // String mit '\0' abschließen if (fprintf_s(stdout, RecvBuf, n) < 0) { fprintf_s(stdout, "Schreib-/Lesefehler!\n"); } //Falls senden fehlgeschlagen ist: Fehlermeldung und beenden mit Tastendruck if (send(sock, SendBuf, static_cast<int>(strlen(SendBuf)), 0) <0) { fprintf_s( stdout, "Fehler beim Senden!\n" ); fprintf_s( stdout, "Zum beenden bitte Taste druecken" ); closesocket( sock ); WSACleanup(); while( !_kbhit() ); exit( EXIT_SUCCESS ); } // Socket schließen und von der Winsock-DLL reservierten Ressourcen freigeben closesocket(sock); WSACleanup(); }//Hauptschleife } // main
-
Ähm ja... Deine Schleifen-Konditionsvariable heißt connect, was in diesem Fall keine Variable sondern eine Funktion ist, auf die der Zeiger immer ungleich 0 ist, was bedeutet, dass die Schleife für immer läuft.
Am Ende der Schleife schließt Du den Socket und räumst WSA auf, wobei du beim nächsten Schleifendurchlauf wieder mit Socket-Funktionen arbeitest?!
cin.getline ();gibst du als Buffer-Größen-Parameter 1000 mit, obwohl der Buffer nur 100 Bytes groß ist. Außerdem verwendest du zwei Malsend ();, wobei du nur beim zweiten Mal prüfst, ob ein Fehler aufgetreten ist...Mein Tipp: Schmeiß den Code weg und fang noch mal ordentlich an. Ein gutes Tutorial findest du hier.
-
Ah ok. Die Differenz 100 zu 1000 war nur Testweise, habs vergessen zu ändern.
Ansonsten Danke für den Tipp. Werd das dann morgen mal in Angriff nehmen.
Falls es nicht klappt, meld ich mich hier wiederSchönen Abend noch
-
Vielleicht solltest du den Code selbst paar mal durchgehen bis es klingelt, bevor du hier postest...