Socket Problem



  • Habe den Rückgabewert von recv() geprüft. Gibt immer -1 zurück.



  • Kann es vielleicht auch sein, dass der Socket falsch initialisiert ist oder mit der Nachrichten verarbeitung etwas nicht stimmt?
    Spielt es eine Rolle wie ich WM_SOCKET definiere
    (#define WM_SOCKET (WM_USER+1)?



  • WSAAsyncSelect() macht den Socket asynchron, d.h. recv() blockiert nicht mehr!

    MSDN schrieb:

    The WSAAsyncSelect function automatically sets socket s to nonblocking mode, regardless of the value of lEvent.

    Ich wette -1 entspricht dem in der MSDN angegebenen SOCKET_ERROR und WSAGetlastError() wird die dann noch WSAEWOULDBLOCK zurückliefern.

    MSDN schrieb:

    This error is returned from operations on nonblocking sockets that cannot be completed immediately, for example recv when no data is queued to be read from the socket. It is a nonfatal error, and the operation should be retried later. It is normal for WSAEWOULDBLOCK to be reported as the result from calling connect on a nonblocking SOCK_STREAM socket, since some time must elapse for the connection to be established.

    Lies mal ein wenig in der msdn rum 😉



  • Werde da irgendwie nicht schlau draus
    Habe mal recv() weggelassen und nur eine MessageBox bei FD_READ eingetragen. Die kommt aber nur einmal, eim nächsten senden bzw. empfangen tut sich gar nichts mehr.
    Woher weiß ich mit welcher Version ich den Socket initialisieren muss (WSAStartup)?



  • Nimm immer Winsock 2.0 (für win95 gibts dafür nen update, bei allen folgenden Windows-Versionen ist es vorinstalliert)

    Du kriegst keine weiteren Events, weil du nur beim Server-Socket WSAAsyncSelect() benutzt. Die Sockets zu den Clients bekommst du als Rückgabewert von accept() den du zur Zeit quasi im Nirvana verschwinden lässt, auf diesen müsstest du allerdings auch WSAASyncSelect() anwenden 😉

    Den Socket für den die Notfication kommt steht im wParam von WM_SOCKET...



  • OK, habe folgendes probiert:

    case WM_SOCKET_NOTIFY:
    		SOCKET Socket,clientSocket;	
    		Socket=(SOCKET)(wParam);
    
    		 switch(LOWORD(lParam))
    			{
    			case FD_READ:
    			    //lesen();
    				MessageBox(hwnd,"Nachricht vom Client","",MB_OK);
    				return 0;
    			case FD_ACCEPT:
    				struct sockaddr clientIn;
    				int clientLen;
    				clientLen = sizeof(clientIn);
    				clientSocket=accept(Socket,(struct sockaddr*)&clientIn,&clientLen); 
    				WSAAsyncSelect(clientSocket,hwnd,WM_SOCKET_NOTIFY,FD_READ|FD_CLOSE|FD_ACCEPT);
    
    				SendMessage(hwndLA, LB_DELETESTRING, 0, 0);
    				SendMessage(hwndLA, LB_ADDSTRING, 0, (long)"- verbunden...");
    				return 0;
    

    hat aber auch nicht funktioniert, es kommt immer nur einmal die MessageBox. Wenn ich den Client beende und wieder aufrufe funktioniert es wieder, aber wieder nur einmal.

    Kann das Problem auch bei Client liegen:

    ...
    connectSocket=socket(AF_INET,SOCK_STREAM,0);
    
    memset(&addr,0,sizeof(SOCKADDR_IN));
    addr.sin_family=AF_INET;
    addr.sin_port=htons(5000);
    addr.sin_addr.s_addr=inet_addr("127.0.0.1");
    
    WSAAsyncSelect(connectSocket,hwnd,WM_SOCKET,FD_READ|FD_CLOSE|FD_CONNECT);
    
    connect(connectSocket,(struct sockaddr*)&addr,sizeof(addr));
    
    ...
    	case ID_SEND:
    				    char buf[20];
    				    buf[0]='-';
    
    				    GetWindowText(hwndLC,buf,20);
    
    			    	 if(send(connectSocket,buf,20,0)==20){
    				       SendMessage(hwndLB,LB_INSERTSTRING, 0,(long)buf);
                           SetWindowText(hwndLC,0);
    					 }
    
    				    break;
    


  • Holst du auch bei jedem FD_READ sämtliche Daten (via recv z.B.) aus dem Empfangsbuffer? Weitere FD_READ-Nachrichten für denselben Socket werden von Winsock unterdrückt solange die Daten für das erste FD_READ nicht vollständig aus dem Empfangsbuffer geholt worden sind...



  • Bin begeistert, es funktioniert.
    Vielen Dank für die Hilfe.



  • geeky schrieb:

    Holst du auch bei jedem FD_READ sämtliche Daten (via recv z.B.) aus dem Empfangsbuffer? Weitere FD_READ-Nachrichten für denselben Socket werden von Winsock unterdrückt solange die Daten für das erste FD_READ nicht vollständig aus dem Empfangsbuffer geholt worden sind...

    A single recv in response to each FD_READ message is appropriate.



  • Ok, da hat mich mein Gedächtnis wohl verarscht 😉



  • Hätte noch ein anderes Problem.
    Wenn ich den Client starte zeigt er mir an, dass ich verbunden bin obwohl noch kein Server existiert. Das heißt wohl er bekomt ein FD_CONNECT ohne verbunden zu sein.



  • Gibt es ein anderes Socket-Evenet, mit dem ich abfragen kann ob ein Server vorhanden ist?



  • wenn der connect fehlschlägt, also kein server da ist bzw. keiner gefunden, gibt es als return code "SOCKET_ERROR".

    das problem liegt wohl an deinem programm, das du irgendwo etwas falsch ausgibts. wenn der server nicht da ist, kann sich der socket nicht dahin connecten.



  • Wenn kein Server vorhanden ist bekomme ich auch SOCKET_ERROR aber anschließend trotzdem FD_CONNENCT. Was könnte falsch sein?

    ...
    	WSADATA wsa;
    	rc=WSAStartup(MAKEWORD(2,0),&wsa);
    
    ...
    
    	clientSocket=socket(AF_INET,SOCK_STREAM,0);
    
    	WSAAsyncSelect(clientSocket,hwnd,WM_SOCKET_NOTIFY,FD_READ|FD_CLOSE|FD_CONNECT);
    
    	memset(&addr,0,sizeof(SOCKADDR_IN));
    	addr.sin_family=AF_INET;
    	addr.sin_port=htons(port);
    	addr.sin_addr.s_addr=inet_addr(ip);
    
    	rc = connect(clientSocket,(struct sockaddr*)&addr,sizeof(addr));
    
    	if( rc == SOCKET_ERROR)
    	{
    
    		SendMessage(hwndLA, LB_DELETESTRING, 0, 0);
    		SendMessage(hwndLA, LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(TEXT("- connect Fehler")));	
    		return;	
    	}
    
    ...
    
        case WM_SOCKET_NOTIFY:
    
    		switch(LOWORD(lParam))
    			{
    ...
    
    			case FD_CONNECT:
    				SendMessage(hwndLA, LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(TEXT("- Verbunden")));
    
    				return 0;
    
    ...
    


  • Dann prüf doch auf Fehler mit dem Makro WSAGETSELECTERROR auf lParam.



  • WSAGetLastError liefert: WSAEWOULDBLOCK



  • lern mal lesen junge



  • Sorry für meine Ausdrucksweise. Wenn du FD_CONNECT bekommst kannst du nicht mehr WSAGetLastError benutzen sondern der Error-Code befindet sich dann in lParam und kann mit WSAGETSELECTERROR extrahiert werden.



  • Ich dachte das käme aufs gleiche raus.
    WSAGETSELECTERROR(lParam) liefert : WSAECONNREFUSED



  • Ok, Problem gelöst vielen Dank für die Hilfe.
    Trotzdem komisch, dass der Client FD_CONNECT gepostet bekommt obwohl WSAGETSELECTERROR WSAECONNREFUSED liefert


Anmelden zum Antworten