Viele Fragen zu WinSock...
-
Hey!
Ich hab nen ganzen Haufen Fragen zu WinSock und dessen Techniken. Ein umfangreiches FAQ wäre auch toll.
Jede Frage gilt für TCP/UDP und blocking/non-blocking, also wenn es Unterschiede gibt, sollen diese bitte erläutert werden.
-
Muss bei einem send/recv abgefragt werden, wieviele Daten gesendet/empfangen wurden und gegebenfalls weiter gesendet/empfangen werden, oder wird bei einem Aufruf immer alles gesendet/empfangen?
-
Sind die (oder welche?) socket-Funktionen threadsafe? Wenn ja, in welcher Weise? Kann ich in zwei oder mehr Threads gleichzeitig send'en/recv'en (wenn non-blocking)?
-
Wieviele sockets braucht man zum Senden und Empfangen? Reicht ein einziges socket zum vielfachen gleichzeitigen Empfangen/Senden?
-
Welche Möglichkeiten hat man/welche ist die beste um mehrere Clients zu bedienen? select? Threads? WSAAsyncSelect? WSAEventSelect? Was sind da die Vor- und Nachteile? Für was eignet es sich (Onlinespiel-server, remote control server, ..)?
Da war noch mehr in meinem Kopf, aber ich bin verwirrt und hab es vergessen.
So viele Unklarheiten

Vielen Dank jedenfalls für jede Hilfe!
MfG,
Der Netzwerknoob
-
-
Netzwerknoob schrieb:
- Muss bei einem send/recv abgefragt werden, wieviele Daten gesendet/empfangen wurden und gegebenfalls weiter gesendet/empfangen werden, oder wird bei einem Aufruf immer alles gesendet/empfangen?
Du musst abfragen, wieviel gesendet/empfangen wurde (steht übrigens auch in der MSDN).
Netzwerknoob schrieb:
- Sind die (oder welche?) socket-Funktionen threadsafe? Wenn ja, in welcher Weise? Kann ich in zwei oder mehr Threads gleichzeitig send'en/recv'en (wenn non-blocking)?
Afaik sind die Funktionen nicht thread-safe.
Netzwerknoob schrieb:
- Wieviele sockets braucht man zum Senden und Empfangen? Reicht ein einziges socket zum vielfachen gleichzeitigen Empfangen/Senden?
Merkwürdige Frage irgendwie. Für jede Verbindung brauchst du einen Socket und kannst damit Senden und Empfangen. Hast du nur eine Verbindung zu einem anderen Rechner, reicht auch ein Socket. Hast du (z.B. als Server) Verbindungen zu mehreren Rechnern, brauchst du auch mehrere Sockets, pro Verbindung ein Socket halt.
Netzwerknoob schrieb:
- Welche Möglichkeiten hat man/welche ist die beste um mehrere Clients zu bedienen? select? Threads? WSAAsyncSelect? WSAEventSelect? Was sind da die Vor- und Nachteile? Für was eignet es sich (Onlinespiel-server, remote control server, ..)?
Afaik sind I/O Completion Ports ganz gut, unter Linux epoll.
selectskaliert sehr schlecht.
-
Badestrand schrieb:
Du musst abfragen, wieviel gesendet/empfangen wurde (steht übrigens auch in der MSDN).
Es ist sehr schlecht dokumentiert. Es gibt nämlich Unterschiede zwischen UDP/TCP, nur weiß ich nicht mehr welche. Bei einem der beiden kann man sich AFAIR darauf verlassen, dass die Funktionen send/recv/... mit einem call alle Daten verarbeiten (=senden/empfangen?).
Badestrand schrieb:
Afaik sind die Funktionen nicht thread-safe.
Ok, würde es halt gerne wissen.
Badestrand schrieb:
Merkwürdige Frage irgendwie. Für jede Verbindung brauchst du einen Socket und kannst damit Senden und Empfangen. Hast du nur eine Verbindung zu einem anderen Rechner, reicht auch ein Socket. Hast du (z.B. als Server) Verbindungen zu mehreren Rechnern, brauchst du auch mehrere Sockets, pro Verbindung ein Socket halt.
Aha, ok, ich denke das habe ich verstanden.
Badestrand schrieb:
Afaik sind I/O Completion Ports ganz gut, unter Linux epoll.
selectskaliert sehr schlecht.Ah, dass select schlecht skaliert, dachte ich echt nicht.
Freue mich über weitere Antworten.
MfG,
Der Netzwerknoob
-
Netzwerknoob schrieb:
Badestrand schrieb:
Du musst abfragen, wieviel gesendet/empfangen wurde (steht übrigens auch in der MSDN).
Es ist sehr schlecht dokumentiert. Es gibt nämlich Unterschiede zwischen UDP/TCP, nur weiß ich nicht mehr welche. Bei einem der beiden kann man sich AFAIR darauf verlassen, dass die Funktionen send/recv/... mit einem call alle Daten verarbeiten (=senden/empfangen?).
Zu "send":
MSDN schrieb:
If no error occurs, send returns the total number of bytes sent, which can be less than the number indicated by len.
Und zu UDP noch:
MSDN schrieb:
For message-oriented sockets, care must be taken not to exceed the maximum packet size of the underlying provider, which can be obtained by using getsockopt to retrieve the value of socket option SO_MAX_MSG_SIZE. If the data is too long to pass atomically through the underlying protocol, the error WSAEMSGSIZE is returned, and no data is transmitted.
Hört sich wirklich so an, als würde bei UDP entweder alles oder garnix gesendet werden. Hoffe, jemand weiß es noch genauer.
Der Unterschied zwischen blocking<->non-blocking ist bei send/recv nur, dass du bei non-blocking warten musst bis der Socket bereit ist.
-
Die Socket-Funktionen sind soweit ich weiss sehrwohl Thread-Safe. Natürlich nur, wenn du den "rohen" Socket verwendest. Sobald du irgendwelche Wrapper-Klassen verwendest, musst du wissen ob diese Klassen Thread-Safe sind (was sie oft nicht sind).
Was UDP angeht: ja, UDP ist "alles oder nichts". Liegt in der Natur der Sache.
Weiters reicht bei UDP ein Socket um mit vielen Peers zu kommunizieren.
-
Aha ok super, danke!
Was ich nun bei Completion Ports nicht verstehe, ist, dass man anscheinend auf I/O, also beides, warten soll/kann?
Wie soll man auf einen Output warten? Ich dachte, damit wartet man, bis ein Client etwas schickt, also man wartet immer nur auf Input... Senden kann man doch, wann man will (Sobald die Verbindung steht)?MfG,
Der Netzwerknoob
-
Netzwerknoob schrieb:
Wie soll man auf einen Output warten? Ich dachte, damit wartet man, bis ein Client etwas schickt, also man wartet immer nur auf Input... Senden kann man doch, wann man will (Sobald die Verbindung steht)?
wenn die gegenstation die daten zu langsam abholt und dein sendebuffer voll ist, dann musste warten, bis es weitergeht.

-
Aha, aber GetQueuedCompletionStatus() ist doch ein blocking call. Wie soll ich da vernünftig senden können (Wenn ich zB. per Button-Klick etwas senden möchte)?
MfG,
Der Netzwerknoob
-
Achso, ich denke, ich kapiere es jetzt. Man sendet und sollte dann erst auf eine Output-Completion warten. Wenn dort dann was schief läuft, könnte der Sendepuffer voll sein oder sonst was fehlschlagen...
MfG,
Der Netzwerknoob
-
Netzwerknoob schrieb:
Aha, aber GetQueuedCompletionStatus() ist doch ein blocking call. Wie soll ich da vernünftig senden können (Wenn ich zB. per Button-Klick etwas senden möchte)?
die funktion ist doch für 'nen extra thread gedacht. der kann ruhig warten, bis das ereignis eintritt. kannst auch 'nen timeout angeben: http://msdn.microsoft.com/en-us/library/aa364986.aspx

-
Jo danke, aber das weiß ich schon.
Habe nun paar Tutorials gelesen, kapiere es aber nicht. Warum ist AcceptEx() so doof designed, dass gleich ein receive mit eingebaut ist? Verstehe ich das richtig, dass ich noch einen extra Thread brauche, welcher nach "stale clients" prüft, also clients, die sich verbunden, aber noch nix gesendet haben (DoS Attack)?
Und soll man nun einen oder mehrere Threads mit AcceptEx() verwenden? Wenn nämlich gerade ein client verbindet, aber noch nix sendet, können doch keine anderen clients verbinden...
(Vielleicht ein Tutorial, wo nicht so kryptische Kacke (oder MFC) wie hier http://msdn.microsoft.com/en-us/magazine/bb985148.aspx verwendet wird? (OverlapPlus, Overlap, OVERLAPPEDPLUS, ol, in einer Zeile, toll...))

MfG,
Der Netzwerknoob
-
Warum ist AcceptEx() so doof designed, dass gleich ein receive mit eingebaut ist?
das receive ist doch optional
-
Oh, das ging mir aus dem Tutorial irgendwie nicht hervor. Auch verwirrt mich dort, warum "socket(AF_INET, SOCK_STREAM, 0);" geschrieben wird und nicht "WSASocket(AF_INET, SOCK_STREAM, 0, 0, 0, WSA_FLAG_OVERLAPPED);".
MfG,
Der Netzwerknoob
-
Und warum muss anscheinend irgend ein Funktionszeiger von AcceptEx() geholt werden? Reicht es nicht, einfach die Funktion aufzurufen?

MfG,
Der Netzwerknoob
-
Reicht, ist aber langsamer.
-
Ok danke, bleiben noch 3 Fragen.
MfG,
Der Netzwerknoob
-
Öh sorry, eigentlich ... brauche ich nur ein ordentliches Tutorial...
MfG,
Der Netzwerknoob
-
Wie ist das mit AcceptEx(), muss ich das so machen:
Einmal beim Start des Programmes, und dann immer bei GetQueuedCompletionStatus() und OP_ACCEPT gleich ein neues AcceptEx() aufrufen?
Gibt es da dann keine Lücke, wo ein Client keine acception bekommt?MfG,
Der Netzwerknoob
-
Die Listen Queue ist doch auch noch da.
-
Ich weiß nicht, was du meinst.
MfG,
Der Netzwerknoob