WinSocks beim start starten...



  • Wenn du auf den Listening-Socket WSAAsyncSelect() aufgerufen hast, bekommst du ein FD_ACCEPT sobald ein Client sich mit deinem Server verbinden will.
    Daraufhin solltest du dann accept() aufrufen.



  • OK ok das hab ich jetzt auch verstanden (juhu!!)

    Jetzt habe ich aber wieder ein neues Problem:

    Ich mache ja für den Chat so eine Server-Liste (Siehe Bild oben^^), dh. da werden alle Server aufgelistet sein die eine Verbindung zu mir aufnehmen wollen.
    Aber wie finde ich Info's wie den Namen, den der chat-partner beim server angegeben hat heraus??? Unzwar muss das ja noch vor accept() sein, weil wenn mehrere Server zu mir connecten wollen kann ich mich ja schlecht mit jedem verbinden^^, da müsste ich ja ziemlich viele Sockets erstellen^^

    Kann der Server, noch bevor er sich mit dem Clienten verbindet, einige Info's schicken, damit man auch den Namen in der Liste sehen kann???

    Protokoll ist TCP



  • nein - ohne Verbindung kannst du nix übertragen, sonst wäre die Verbindung ja unnötig (bei TCP) 😉

    Abgesehen davon verbindet sich kein Server mit einem Client sondern andersherum, sonst wäre der Server kein Server.
    Der Server kann die Verbindung vom Client nur annehmen oder eben nicht.
    (Es sei denn das Server-Programm enthält sowohl eine Client- als auch Server-Komponente)

    Wenn du weniger Verbindungen haben willst, nimm doch ein verbindungsloses Protokoll wie UDP (welches aber auch wieder seine Nachteile hat).



  • geeky schrieb:

    nein - ohne Verbindung kannst du nix übertragen, sonst wäre die Verbindung ja unnötig (bei TCP) 😉

    Abgesehen davon verbindet sich kein Server mit einem Client sondern andersherum, sonst wäre der Server kein Server.
    Der Server kann die Verbindung vom Client nur annehmen oder eben nicht.
    (Es sei denn das Server-Programm enthält sowohl eine Client- als auch Server-Komponente)

    Wenn du weniger Verbindungen haben willst, nimm doch ein verbindungsloses Protokoll wie UDP (welches aber auch wieder seine Nachteile hat).

    Heißt das wenn ich so eine liste machen will muss ich jede einzelne verbindung einmal akzeptieren um info's in die liste zu schreiben? (OMG das wird ne komplizierte Funktion... -.- rofl...)

    Aber die ip muss man ja herausfinden können bevor man accept()et, oder?
    Wie mache ich das?



  • accept() liefert bei Verbindungsannahme optional die IP mit.
    Ansonsten gibt es noch getpeername, was aber auch nur mit einem verbundenen Socket funktioniert.



  • Nagut diese frage da hat sich geklärt^^
    Ich denk mal das besste ist, wenn ich 2 ports benutze^^

    habe jetzt aber eine andere:
    Wie kann ich mit connect() in regelmäßigen zeitabständen prüfen ob der server da ist, ohne zu blockieren?
    Ich habe es mit einer Schleife und sleep probiert, doch da wird logischer Weise bockiert -.-

    Kennt jemand eine bessere Lösung??



  • Nimm wieder WSAAsyncSelect() (vor Aufruf von connect() ) und du bekommst eine FD_CONNECT Nachricht wenn es geklappt hat.

    Die meisten Anwendungen scheinen allerdings für sowas einfach nen Thread zu starten und da drin mit blockierenden Sockets zu arbeiten.



  • geeky schrieb:

    Nimm wieder WSAAsyncSelect() (vor Aufruf von connect() ) und du bekommst eine FD_CONNECT Nachricht wenn es geklappt hat.

    Die meisten Anwendungen scheinen allerdings für sowas einfach nen Thread zu starten und da drin mit blockierenden Sockets zu arbeiten.

    Das dumme ist nur, das ich immer (!) eine FD_CONNECT message bekomme^^, selbst wenn nix verbunden ist^^

    Hier der komplette Source vom Clienten:
    http://nopaste.com/p/avSrghNvD
    http://nopaste.com/p/aNzR5ZIV6
    http://nopaste.com/p/aIcIu57rN



  • Habe jetzt einen neuen thread für Connect angelegt, weil man mit FD_CONNECT anscheinend nixx anfangen kann -.-

    Funktioniert auch ganz gut aba irgendwas habe ich in der Schleife falsch gemacht und finde den Fehler einfach nicht:

    DWORD WINAPI ThreadFunktion(LPVOID param)
    {
    	while(test2 == SOCKET_ERROR)
    	{
    		test2 = connect(s, (SOCKADDR*)&addr, sizeof(SOCKADDR_IN));
    		if(test2 == SOCKET_ERROR)
    		{
    			AddText("Fehler: Connection gescheitert!");
    			Sleep(1000);
    		}
    		else
    		{
    			AddText("Verbunden mit 127.0.0.1 .!");
    			return 1;
    		}
    	}
    	return 0;
    }
    

    Also wenn man den Server zuerst an macht und danach den Clienten, dann funktioniert auch alles richtig. Also er sagt:
    "Verbunden mit 127.0.0.1 .!"

    Aber wenn ich zuerst den Clienten an mache und danach den Server, dann sagt er immer: "Fehler: Connection gescheitert!"
    Doch der Server sagt das eine Verbindung akzeptiert wurde und der Client hat sogar "Hallo" geschickt, obwohl der Client die ganze zeit "Fehler: Connection gescheitert!" ausgibt -.-

    Also irgendwie ist das komisch.... Liegt es evtl daran das die variable "test2" global ist??? Aber local kann ich da keine Variale anlegen....



  • Wieso solltest du in einer Thread-Funktion keine lokale Variable anlegen können?
    Kann es sein, dass test2 auch noch irgendwo außerhalb des Threads bearbeitet wird?

    Rob'



  • Werte den Fehler mal näher aus: WSAGetLastError()

    In deiner WM_SOCKET: Werte noch WSAGETSELECTERROR() aus.
    Eventuell kriegste bei FD_CONNECT auch noch was zu dem merkwürdigen Verhalten über den Socket (steht in wParam) raus, für den da Windows dir ein FD_CONNECT verschaukelt 😉

    (Variablen/Objekte die du in mehreren Threads benutzt solltest du synchronisieren)



  • Sooo..... Habe Problem gelöst(Aber habe wieder ein weiteres Problem, siehe unten):

    Wenn ich zuerst WSAAsyncSelect() aufgerufen habe und danach connect(), dann sendet er IMMER eine FD_CONNECT Message.
    ABER wenn ein Fehler beim Verbinden aufgetreten ist, dann füllt er den WORD: wError = WSAGETSELECTERROR(lParam); mit dem error.

    Und dann kann man das ganz einfach mit einer if Anweiung checken:

    case FD_CONNECT:
    
    							if (wError)
    							   {
    									AddText("Warte auf Verbindung");
    									connect(s, (SOCKADDR*)&addr, sizeof(SOCKADDR_IN));
    									return TRUE ;
    							   }
    
    							    AddText("Verbunden mit 127.0.0.1 .!");
    							    return 0;
    

    Ohne das ich irgendwelche threads oder Schleifen brauche, weil FD_CONNECT ja immer aufgerufen wird sobald man die Funktion connect() ausgeführt hat^^

    Jedoch bin ich mir nicht ganz Sicher was das angeht weil bei FD_CLOSE klappt das dummerweise nicht -.-

    case FD_CLOSE:
    							AddText("Verbindung abgebrochen!");
    							connect(s, (SOCKADDR*)&addr, sizeof(SOCKADDR_IN));
    

    Weil Wenn Client und Server miteinander verbunden sind und der Server plötzlich off geht, dann muss der Client ja weiter prüfen ob eine Verbindung besteht , falls der Server wieder online geht
    Aber wenn ich in der message connect() ausführe, dann wird komischerweise keine FD_CONNECT Nachricht geschickt
    Weiß vllt einer woran das liegen kann???



  • Ich habe jetzt mal die Rückgabewerte mit WSAGetLastError() gecheckt:

    naja als erstes gabs den Fehler:

    Socket is already connected.

    Dann habe ich closesocket(s) aufgerufen, danach hatte ich gleich nen Weiteren Fehler:

    Socket operation on nonsocket.

    Dann habe ich Socket s nochmal neu erstellt und jetzt kriege ich die richtige fehlermeldung:

    Connection refused.

    ABER FD_CONNECT WIRD TRODSTEM NICHT GESENDET!!!!
    MAN langsam werde ich hier.....

    Ka was ich jetzt machen soll.... hat vllt jemand eine Idee??



  • Ok habe den Fehler grade selber gefunden:

    Weil ich den Socket s in FD_CLOSE geschlossen habe und ihn danach neu erstellt habe, musste ich auch

    WSAAsyncSelect(s, hWnd, WM_SOCKET, FD_CONNECT | FD_WRITE | FD_READ | FD_CLOSE);
    

    nochmal aufrufen^^


Anmelden zum Antworten