Wir schreiben einen Client und einen Server zu tun (was ich dachte, war) ziemlich einfache Netzwerk-Kommunikation. Mehrere Clients verbinden sich mit dem Server, der die Daten dann an alle anderen Clients zurücksenden soll.Lesen und Schreiben in den gleichen Socket (TCP) mit Select
Der Server sitzt nur in einer blockierenden select
Schleife auf Datenverkehr, und wenn es dazu kommt, sendet die Daten an die anderen Clients. Das scheint gut zu funktionieren.
Das Problem ist der Client. Als Antwort auf einen Lesevorgang möchte er manchmal schreiben.
Allerdings habe ich festgestellt, dass, wenn ich benutze:
rv = select(fdmax + 1, &master_list, NULL, NULL, NULL);
Mein Code wird blockiert, bis neue Daten zu lesen ist. Aber manchmal (asynchron, von einem anderen Thread) habe ich neue Daten, um auf den Netzwerk-Kommunikations-Thread zu schreiben. Also, ich möchte meine wählen regelmäßig aufwachen und lassen Sie mich prüfen, ob Daten zu schreiben sind, wie:
if (select(....) != -1)
{
if (FD_SET(sockfd, &master_list))
// handle data or disconnect
else
// look for data to write and write()/send() those.
}
I Einstellung versucht, den Auswahlmodus (oder lächerlich kurzen Timeouts) abfragen mit:
// master list contains the sockfd from the getaddrinfo/socket/connect seq
struct timeval t;
memset(&t, 0, sizeof t);
rv = select(fdmax + 1, &master_list, NULL, NULL, &t);
aber haben festgestellt, dass dann Client nie eingehende Daten erhält.
Ich habe auch versucht die Buchse fd Einstellung nicht blockierend zu sein, wie:
fcntl(sockfd, F_SETFL, O_NONBLOCK);
aber das löst nicht das Problem:
- , wenn mein Kunde
select()
keinstruct timeval
hat, Lesen Daten funktionieren, aber es gibt keine Blockierung, um nach schreibbaren Daten zu suchen. - Wenn mein Client
select()
hat einetimeval
, um es zu Abfrage, dann signalisiert es nie, dass eingehende Daten zu lesen sind, und meine App einfriert denken, es gibt keine Netzwerkverbindung (trotz der Tatsache, dass alle anderen Funktionsaufrufe erfolgreich waren)
Irgendwelche Hinweise überhaupt, was ich falsch machen könnte? Ist es nicht möglich, Read-Write am gleichen Socket zu machen (ich kann nicht glauben, dass das wahr ist).
(EDIT: Die richtige Antwort, und was ich auf dem Server in Erinnerung, aber nicht auf dem Client, ist eine zweite fd_set zu haben, und kopiert Master_List vor jedem Anruf zu wählen():
// declare and FD_ZERO read_fds:
// put sockfd in master_list
while (1)
{
read_fds = master_list;
select(...);
if (FD_ISSET(read_fds))
....
else
// sleep or otherwise don't hog cpu resources
}
)
Sorry, dass if (FD_SET (... sollte if (FD_ISSET (.... – MarcWan