![]() |
Chat Server empfängt immer nur einmal
Ich bin gerade dabei einen kleinen Chat mit Server und Clients zu programmieren. Dabei benutze ich keine Komponenten. Der Server wartet dabei in einem Thread auf Clients, die sich verbinden. Jeder Client kommt in ein Array. Dann geht der Server im Thread jedes mal dieses Array durch und guckt, ob vom entsprechenden Client was kommt:
Delphi-Quellcode:
Aber irgendwie kann ich nur einmal was an den Server senden. Alles weitere kommt nicht an. irgendwo, muss da ein Denkfehler von mir sein. :gruebel:
function ServerThread(p: Pointer): Integer;
var TempConSocket: TSocket; i: Integer; MsgBuffer: array[0..255] of Char; resourcestring rsListen = 'Listening...'; rsSocketOK = 'Neuer Client hat sich verbunden.'; rsSocketError = 'Ungültige Socket'; rsMsg = 'Client: %s'; begin bRunning := True; if listen(acceptSock, 10) <> SOCKET_ERROR then begin AddLogText(hApp, IDC_LV, rsListen, 2); while bRunning do begin listen(acceptSock, 10); TempConSocket := accept(acceptSock, nil, nil); if TempConSocket <> INVALID_SOCKET then begin SetLength(conSocket, length(conSocket)+1); conSocket[High(conSocket)] := TempConSocket; AddLogText(hApp, IDC_LV, rsSocketOK, 2); end else AddLogText(hApp, IDC_LV, rsSocketError, 0); for i := 0 to length(conSocket) - 1 do begin if recv(conSocket[i], MsgBuffer, sizeof(MsgBuffer), 0) > 0 then AddLogText(hApp, IDC_LV, Format(rsMsg, [String(MsgBuffer)]), 2); Zeromemory(@MsgBuffer, sizeof(MsgBuffer)); end; end; end else AddLogText(hApp, IDC_LV, SysErrorMessage(WSAGetLastError), 0); result := 0; end; |
Re: Chat Server empfängt immer nur einmal
Hallo Luckie
Zitat:
|
Re: Chat Server empfängt immer nur einmal
du verwendest die Sockets im Blocking-Mode, sprich:
Thread startet, listen macht Port auf, accept blockiert, bis eine Connection eingeht, danach blockiert recv, bis das erste TCP-Segment eintrifft, danach wieder accept, welches aber blockiert, bis eine Connection eingeht, danach blo.... while true do ; :-) entweder lässt du einen Thread als Listener laufen, der dann pro akzeptierter Connection einen weiteren Thread spawned... oder du betreibst die Sockets im Non-Blocking-Mode.... mehr dazu in der WinSock-Referenz (Stichworte: select / ioctlsocket) |
Re: Chat Server empfängt immer nur einmal
Aaaah. Danke, das war meine Wissenslücke. Ich habe jetzt für jeden neuen Client einen eigenen Thread. Nur habe ich jetzt ein konzeptionelles Problem:
Delphi-Quellcode:
Ich habe jetzt alle Nachrichten, die ankommen, "auf dem Server". Wie verteile ich sie jetzt am besten wieder auf die Clients? :gruebel:
function ClientThread(p: Pointer): Integer;
var Sock: TSocket; MsgBuffer: array[0..255] of Char; resourcestring rsMsg = 'Client: %s'; begin Sock := PClientThreadParams(p)^.Sock; while True do begin if recv(Sock, MsgBuffer, sizeof(MsgBuffer), 0) > 0 then AddLogText(hApp, IDC_LV, Format(rsMsg, [string(MsgBuffer)]), 2); end; FreeMem(p, sizeof(TClientThreadParams)); end; |
Re: Chat Server empfängt immer nur einmal
vermutlich wirst du nicht um den Non-Blocking-Mode herumkommen.... und für die Kommunikation zwischen den Client-Threads wird irgend eine Art von Thread-Safen Queue benötigt...
pseudo-code:
Code:
(wobei die *DataAvailable für beispielsweise 200ms blockieren, wenn keine Daten vorhanden sind, so dass nicht die gesamte CPU beübt wird.... die daraus resultierende Latenz ist bei einem Chat-System nicht störend...)
while ClientConnected do begin
if networkDataAvailable then pushQueueData if queueDataAvailable then sendNetworkData end; auf Dinge wie concurrent Socket-Operationen mehrere Threads auf dem selben Socket würde ich mich nicht einlassen... das kracht über kurz oder lang... PS: hier spielst du mit dem Feuer (access violation / live lock):
Delphi-Quellcode:
besser so:
while True do
begin if recv(Sock, MsgBuffer, sizeof(MsgBuffer), 0) > 0 then AddLogText(hApp, IDC_LV, Format(rsMsg, [string(MsgBuffer)]), 2); end;
Delphi-Quellcode:
while true do begin
r:=recv(Sock, MsgBuffer, sizeof(MsgBuffer) - 1, 0); // #0 muss auch Platz haben if not (r > 0) then break; // recv gibt 0 zurück, wenn Connection geschlossen wurde MsgBuffer[r]:=#0; AddLogText(hApp, IDC_LV, Format(rsMsg, [string(MsgBuffer)]), 2); end; |
Re: Chat Server empfängt immer nur einmal
Zitat:
Zitat:
` Zitat:
Zitat:
|
Re: Chat Server empfängt immer nur einmal
Zitat:
Zitat:
"Port Broadcasts" gibts nicht. als Quit'n'Dirty Variante könntest du die Windows-Message-Queue missbrauchen (PostThreadMessage, etc). So must du nicht selber eine thread-safe queue implementieren. und innerhalb der Client-Threads mit select() für einige 100ms auf Netzwerk-Daten warten, dann kurz die Window-Message-Queue prüfen, danach wieder auf Netzwerk-Daten warten. Du brauchst dann lediglich ein Array auf alle Thread-IDs, die allerdings wieder thread-safe sein muss.... Zitat:
ein grundlegend anderer Ansatz wäre, alle Sockets mit einem einzigen Thread zu bedienen: - Socket auf non-blocking schalten - mittels select() auf ein Ereignis (eingehende Verbindung oder Daten vorhanden) eines der vorhandenen Sockets (Server-/Client-Sockets) warten - entsprechend reagieren (Connection akzepiteren, Daten lesen und weitersenden) würde ich jedoch nicht verwenden: - keine saubere Kapselung der Clients gegeneinander - riesiger Thread-Code, unübersichtlich, fehleranfällig |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:33 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz