Wir haben einen Code zum Senden von Metriken an einen SOCK_DGRAM
, wo ein anderer Daemon diese Nachrichten überwacht und aggregiert/proxisiert. die Fassung zu öffnen wie folgt aussieht:Senden an einen Datagramm-Socket, ohne unbegrenzt zu blockieren
sock <- socket
(ai :: AddressInfo Inet Datagram UDP):_ <- getAddressInfo (Just "127.0.0.1") Nothing aiNumericHost
connect s (socketAddress ai) { port }
return sock
Und im Moment sind wir es schreiben:
send sock payload mempty
Ich mag den Anruf, um sicherzustellen, oben nicht sehr lange blockiert (oder zumindest nicht unbegrenzt blockieren), aber mein Verständnis von Unix-Sockets ist nicht sehr tief und ich habe Probleme zu verstehen, wie genau send
blockiert, Blick auf Interna here und here.
Es gibt eine ähnliche Frage hier, die hilfreich war: When a non-blocking send() only transfers partial data, can we assume it would return EWOULDBLOCK the next call?
So sind meine Fragen im Einzelnen:
- Allgemeine Socket Frage: Ich in dieser Implementierung sehe
send
(nach busy-Warte blockieren wird) bis im Puffer Platz ist. Wie genau bezieht sich dieser Puffer auf den Verbraucher? Bedeutet das,send
kann unbegrenzt blockieren, wenn unserlisten
-ing-Daemon langsam ist oder abstürzt? - Wenn ich lieber abbrechen und nie blockieren würde, muss ich meine eigene Gabel von
System.Socket.Unsafe
machen, oder fehle ich etwas?
Ich bin nur mit Linux hier betroffen.
EDIT: Auch, und was hatte ich wahrscheinlich mit all diesem gestartet ist finde ich, dass, wenn der Kollektor Metriken nicht ausgeführt wird, dass jeder andere meiner send
Anrufe über eine „Verbindung abgelehnt“ Ausnahme auslöst. Warum das so ist oder ob es normal ist, ist eine andere Frage, die ich habe.
EDIT2: Hier ist ein vollständiges Beispiel die Verbindung abgewiesen Problem darstellt, wenn jemand repro möchte helfen:
import Data.Functor
import System.Socket
import System.Socket.Family.Inet
repro :: IO()
repro = do
let port = 6565
(s :: Socket Inet Datagram UDP) <- socket
(ai :: AddressInfo Inet Datagram UDP):_ <- getAddressInfo (Just "127.0.0.1") Nothing aiNumericHost
connect s (socketAddress ai) { port }
putStrLn "Starting send"
void $ send s "FOO" mempty
void $ send s "BAR" mempty
putStrLn "done"
Ich verwende socket-0.5.3.0
.
EDIT3: dies scheint aufgrund der connect
Aufruf, irgendwie. (Prüfung auf sockets
latest):
{-# LANGUAGE ScopedTypeVariables, OverloadedStrings, NamedFieldPuns #-}
import Data.Functor
import System.Socket
import System.Socket.Protocol.UDP
import System.Socket.Type.Datagram
import System.Socket.Family.Inet
repro :: IO()
repro = do
(s :: Socket Inet Datagram UDP) <- socket
-- Uncommenting raises eConnectionRefused, everytime:
-- connect s (SocketAddressInet inetLoopback 6565 :: SocketAddress Inet)
putStrLn "Starting send"
void $ sendTo s "FOO" mempty (SocketAddressInet inetLoopback 6565 :: SocketAddress Inet)
void $ sendTo s "BAR" mempty (SocketAddressInet inetLoopback 6565 :: SocketAddress Inet)
putStrLn "done"
Wie ich es verstehe wir sollten in der Lage seiner connect
zu verwenden (zumindest den zugrunde liegenden syscall) der Standard festlegen Adresse. Ich habe noch nicht in die Implementierung von connect
in der Bibliothek gegraben.
Ich habe diese geöffnet: https://github.com/lpeterse/haskell-socket/issues/55
STREAM- und DGRAM-Steckdosen funktionieren sehr unterschiedlich. Ein DGRAM-Sockel weiß nicht, ob etwas tatsächlich auf der anderen Seite zu hören ist. Es feuert einfach alles ab, was du ihm in den interstellaren Raum gibst. –
Es sieht so aus, als wäre das 'MSG_DONTWAIT' Flag zu' send' wahrscheinlich relevant. Die Haskell-Schnittstelle leitet die Flags durch und definiert vermutlich die Konstanten irgendwo. Aber mein Verständnis dieser Dinge ist wahrscheinlich flacher als deins. – dfeuer
Ein 'DGRAM'-Socket blockiert einen Sendevorgang nicht. Es legt einfach ein Paket auf das Netzwerk ab, und wenn der Puffer des Empfängers voll ist, wird das Paket verworfen. Es gibt keine Verbindung, also nichts zu blockieren. –