std.net.socket

Umfassende Socket-Abstraktion für TCP, UDP, Unix Domain Sockets und Raw Sockets. Ermöglicht den Aufbau von Client- und Serveranwendungen auf Netzwerkebene – von einfachen Verbindungen bis hin zu nicht-blockierendem I/O mit Poll/Select-Multiplexing. Enthält außerdem Low-Level-Funktionen für ICMP-Ping, ARP-Paketgenerierung und Ethernet-Header-Erstellung.

Diese Unit bildet die Grundlage für alle höheren Netzwerkprotokolle in der Lyx-Standardbibliothek (HTTP, DNS, SMTP etc.).

import std.net.socket;

var listener: TCPListener := TCPListenerNew();
TCPListenerBind(listener, 8080);
TCPListenerListen(listener, 16);   // Backlog: wartende Verbindungen

var conn: TCPConn := TCPListenerAccept(listener);
TCPConnWrite(conn, "Hello\n", 6);
TCPConnClose(conn);


Imports

  • std.net.types
  • std.net.syscalls

Funktionen

Signatur Sichtbarkeit Beschreibung
BufferAlloc(size: int64): int64 pub Alloziert Speicherpuffer der Größe n
BufferFree(buf: int64, size: int64): int64 pub Gibt Speicherpuffer frei

Typen

TCPListener (struct)

Feld Typ
fd int64
Signatur Sichtbarkeit Beschreibung
TCPListenerNew(): TCPListener pub Erstellt neuen TCP-Listener-Socket
TCPListenerSetReuseAddr(listener: TCPListener): int64 pub Aktiviert SO_REUSEADDR am Listener
TCPListenerSetReusePort(listener: TCPListener): int64 pub Aktiviert SO_REUSEPORT am Listener
TCPListenerSetBacklog(listener: TCPListener, backlog: int64): int64 pub Setzt maximale Warteschlangenlänge
TCPListenerBind(listener: TCPListener, addr: int64): int64 pub Bindet Listener an Adressstruktur
TCPListenerBindTo(listener: TCPListener, ip: int64, port: int64): int64 pub Bindet Listener an IP und Port
TCPListenerListen(listener: TCPListener, backlog: int64): int64 pub Startet Verbindungsannahme
TCPListenerAccept(listener: TCPListener): TCPConn pub Nimmt eingehende TCP-Verbindung an
TCPListenerClose(listener: TCPListener) pub Schließt Listener-Socket

TCPConn (struct)

Feld Typ
fd int64
Signatur Sichtbarkeit Beschreibung
TCPConnRead(conn: TCPConn, buf: int64, n: int64): int64 pub Liest Bytes aus TCP-Verbindung
TCPConnWrite(conn: TCPConn, buf: int64, n: int64): int64 pub Schreibt Bytes in TCP-Verbindung
TCPConnClose(conn: TCPConn) pub Schließt TCP-Verbindung
TCPConnSetNodelay(conn: TCPConn, enable: bool): int64 pub Aktiviert oder deaktiviert TCP_NODELAY
TCPConnSetKeepAlive(conn: TCPConn, enable: bool): int64 pub Aktiviert oder deaktiviert Keep-Alive
TCPConnGetError(conn: TCPConn): int64 pub Liest Fehlercode der Verbindung
TCPConnSetRecvBuf(conn: TCPConn, size: int64): int64 pub Setzt Empfangspuffergröße
TCPConnSetSendBuf(conn: TCPConn, size: int64): int64 pub Setzt Sendepuffergröße
TCPConnSetReuseAddr(conn: TCPConn, enable: bool): int64 pub Aktiviert SO_REUSEADDR an Verbindung
TCPConnect(ip: int64, port: int64): TCPConn pub Stellt TCP-Verbindung zu IP:Port her
TCPConnectAddr(ipAddr: IPAddr): TCPConn pub Stellt TCP-Verbindung via IPAddr her

UDPSocket (struct)

Feld Typ
fd int64
Signatur Sichtbarkeit Beschreibung
UDPSocketNew(): UDPSocket pub Erstellt neuen UDP-Socket
UDPSocketBind(sock: UDPSocket, addr: int64): int64 pub Bindet UDP-Socket an Adressstruktur
UDPSocketBindTo(sock: UDPSocket, ip: int64, port: int64): int64 pub Bindet UDP-Socket an IP und Port
UDPSocketSendTo(sock: UDPSocket, buf: int64, n: int64, dest: int64): int64 pub Sendet Datagramm an Zieladresse
UDPSocketSendToAddr(sock: UDPSocket, buf: int64, n: int64, ip: int64, port: int64): int64 pub Sendet Datagramm an IP:Port
UDPSocketRecvFrom(sock: UDPSocket, buf: int64, n: int64, src: int64, addrlen: int64): int64 pub Empfängt Datagramm mit Absenderadresse
UDPSocketRecv(sock: UDPSocket, buf: int64, n: int64, senderIP: int64, senderPort: int64): int64 pub Empfängt Datagramm mit IP und Port
UDPSocketClose(sock: UDPSocket) pub Schließt UDP-Socket
UDPSocketSetReuseAddr(sock: UDPSocket): int64 pub Aktiviert SO_REUSEADDR am UDP-Socket
UDPSocketSetBroadcast(sock: UDPSocket, an: bool): int64 pub Aktiviert SO_BROADCAST — ohne diese Option weist der Kernel jeden Versand an eine Rundrufadresse mit EACCES ab
UDPSocketSetRecvBuf(sock: UDPSocket, size: int64): int64 pub Setzt Empfangspuffergröße
UDPSocketSetSendBuf(sock: UDPSocket, size: int64): int64 pub Setzt Sendepuffergröße
UDPSocketGetError(sock: UDPSocket): int64 pub Liest Fehlercode des UDP-Sockets

RawSocket (struct)

Feld Typ
fd int64
Signatur Sichtbarkeit Beschreibung
RawSocketNew(protocol: int64): RawSocket pub Erstellt Raw-Socket für Protokoll
RawSocketSendTo(sock: RawSocket, buf: int64, n: int64, destAddr: int64): int64 pub Sendet Rohpaket an Zieladresse
RawSocketRecvFrom(sock: RawSocket, buf: int64, n: int64, srcAddr: int64, addrlen: int64): int64 pub Empfängt Rohpaket mit Quelladresse
RawSocketClose(sock: RawSocket) pub Schließt Raw-Socket

ICMPHeader (struct)

Feld Typ
icmp_type uint8
icmp_code uint8
icmp_cksum uint16
icmp_id uint16
icmp_seq uint16
Signatur Sichtbarkeit Beschreibung
ICMPMakeEchoRequest(id: int64, seq: int64): ICMPHeader pub Erstellt ICMP-Echo-Request-Header
ICMPChecksum(data: int64, len: int64): int64 pub Berechnet ICMP-Prüfsumme
ICMPPing(destIP: int64, id: int64, seq: int64, timeoutSecs: int64): int64 pub Sendet ICMP-Ping und wartet auf Antwort
EthernetHeaderCreate(dstMac: MacAddr, srcMac: MacAddr, ethertype: int64): EthernetHeader pub Erstellt Ethernet-Frame-Header
ARPMakeRequest(senderMac: MacAddr, senderIP: int64, targetIP: int64): ARPPacket pub Erstellt ARP-Request-Paket
ARPMakeReply(senderMac: MacAddr, senderIP: int64, targetMac: MacAddr, targetIP: int64): ARPPacket pub Erstellt ARP-Reply-Paket
ARPSerializePacket(eth: EthernetHeader, arp: ARPPacket, buf: int64): int64 pub Serialisiert ARP-Paket in Puffer
MacBroadcast(): MacAddr pub Gibt Broadcast-MAC-Adresse zurück
IPPack(a: int64, b: int64, c: int64, d: int64): int64 pub Packt vier Oktette zu IPv4-Adresse
IPUnpack(ip: int64): IPAddr pub Entpackt IPv4-Adresse in Oktette

Nicht-blockierende Sockets

Signatur Sichtbarkeit Beschreibung
SocketSetNonBlocking(fd: int64): int64 pub Setzt Socket auf nicht-blockierenden Modus
SocketSetBlocking(fd: int64): int64 pub Setzt Socket auf blockierenden Modus
SocketIsNonBlocking(fd: int64): bool pub Prüft ob Socket nicht-blockierend ist

PollFD (struct)

Feld Typ
fd int64
events int16
revents int16

Externe Funktionen

Extern deklarierte Funktionen (aus C-Bibliotheken):

Signatur Beschreibung
sys_poll(fds: int64, nfds: int64, timeout: int64): int64 Wartet auf Ereignisse mehrerer Deskriptoren
sys_select(nfds: int64, readfds: int64, writefds: int64, exceptfds: int64, timeout: int64): int64 Multiplext I/O auf mehrere Deskriptoren
Signatur Sichtbarkeit Beschreibung
SocketPoll(fds: int64, nfds: int64, timeout: int64): int64 pub Wartet auf Ereignisse via poll()
PollFDReadable(fds: int64, index: int64): bool pub Prüft ob Deskriptor lesbar ist
PollFDWritable(fds: int64, index: int64): bool pub Prüft ob Deskriptor schreibbar ist
PollFDError(fds: int64, index: int64): bool pub Prüft ob Deskriptor Fehler hat
FDSetZero(fdSet: int64) pub Leert fd_set-Struktur
FDSet(fd: int64, fdSet: int64) pub Fügt Deskriptor zu fd_set hinzu
FDClr(fd: int64, fdSet: int64) pub Entfernt Deskriptor aus fd_set
FDIsSet(fd: int64, fdSet: int64): bool pub Prüft ob Deskriptor in fd_set gesetzt

ConnectResult (struct)

Feld Typ
success bool
Signatur Sichtbarkeit Beschreibung
TCPConnectNonBlocking(ip: int64, port: int64, timeoutMs: int64): ConnectResult pub Verbindet nicht-blockierend mit Timeout
SocketCanRead(fd: int64, timeoutMs: int64): int64 pub Prüft Lesbarkeit innerhalb Timeout
SocketCanWrite(fd: int64, timeoutMs: int64): int64 pub Prüft Schreibbarkeit innerhalb Timeout

UnixConn (struct)

Feld Typ
fd int64
Signatur Sichtbarkeit Beschreibung
UnixSocketNew(): UnixConn pub Erstellt neuen Unix-Domain-Socket
UnixSocketBind(sock: UnixConn, path: int64): int64 pub Bindet Unix-Socket an Dateipfad
UnixSocketListen(sock: UnixConn, backlog: int64): int64 pub Startet Verbindungsannahme am Socket
UnixSocketAccept(sock: UnixConn): UnixConn pub Nimmt Unix-Socket-Verbindung entgegen
UnixSocketConnect(path: int64): UnixConn pub Verbindet mit Unix-Domain-Socket-Pfad
UnixSocketRead(conn: UnixConn, buf: int64, n: int64): int64 pub Liest Bytes vom Unix-Socket
UnixSocketWrite(conn: UnixConn, buf: int64, n: int64): int64 pub Schreibt Bytes auf Unix-Socket
UnixSocketClose(conn: UnixConn) pub Schließt Unix-Socket
UnixSocketGetPeerCred(conn: UnixConn, pid: int64, uid: int64, gid: int64): int64 pub Liest Peer-Prozessinformationen aus
TCPConnectIPv6(ip6Hi: int64, ip6Lo: int64, port: int64): TCPConn pub Verbindet TCP über IPv6-Adresse
TCPListenerBindIPv6(listener: TCPListener, ip6Hi: int64, ip6Lo: int64, port: int64): int64 pub Bindet Listener an IPv6-Adresse
TCPListenerNewIPv6(): TCPListener pub Erstellt IPv6-TCP-Listener-Socket
UDPSocketNewIPv6(): UDPSocket pub Erstellt IPv6-UDP-Socket
UDPSocketSendToIPv6(sock: UDPSocket, buf: int64, n: int64, ip6Hi: int64, ip6Lo: int64, port: int64): int64 pub Sendet ein UDP-Datagramm an eine IPv6-Adresse; port in Host-Byte-Order

IPv6

Die Unit deckt IPv6 durchgehend ab — von der Socket-Erzeugung bis zum Auslesen der Gegenstelle. Adressen werden als zwei int64-Hälften übergeben (ip6Hi, ip6Lo); die passenden Werte liefert std.net.types mit IPv6MakeHi/IPv6MakeLo, IPv6AnyHi/IPv6AnyLo und IPv6LoopbackHi/IPv6LoopbackLo.

Signatur Beschreibung
SocketNewV6(): int64 neuen IPv6-TCP-Socket anlegen; fd >= 0 bei Erfolg
SocketNew6(): int64 Alias für SocketNewV6 — der in der Spezifikation kanonische Name
BindV6(fd: int64, ip6Hi: int64, ip6Lo: int64, port: int64): int64 an eine IPv6-Adresse binden; port in Host-Byte-Order, 0 bei Erfolg
BindAddr6(fd: int64, ip6Hi: int64, ip6Lo: int64, port: int64): int64 Alias für BindV6
ConnectV6(fd: int64, ip6Hi: int64, ip6Lo: int64, port: int64): int64 mit einer IPv6-Gegenstelle verbinden
ConnectAddr6(fd: int64, ip6Hi: int64, ip6Lo: int64, port: int64): int64 Alias für ConnectV6
UDPSocketBindIPv6(sock: UDPSocket, ip6Hi: int64, ip6Lo: int64, port: int64): int64 IPv6-UDP-Socket zum Empfangen an einen Port binden
TCPListenerAcceptIPv6(listener: TCPListener, outHi: int64, outLo: int64, outPort: int64): TCPConn eingehende IPv6-Verbindung annehmen
UDPSocketRecvFromIPv6(sock: UDPSocket, buf: int64, n: int64, outHi: int64, outLo: int64, outPort: int64): int64 Datagramm empfangen und die Absenderadresse zurückgeben
SocketGetPeerAddrIPv6(fd: int64, outHi: int64, outLo: int64, outPort: int64): int64 IPv6-Adresse der Gegenstelle lesen
SocketGetOwnAddrIPv6(fd: int64, outHi: int64, outLo: int64, outPort: int64): int64 eigene lokale IPv6-Adresse lesen

Die drei out-Parameter sind Zeiger auf int64, nicht Rückgabewerte. Wer eine Angabe nicht braucht, übergibt dort 0 — die Funktion überspringt sie dann.

 
Zu jedem der drei Paare gibt es zwei Namen: SocketNewV6/SocketNew6, BindV6/BindAddr6, ConnectV6/ConnectAddr6. Es sind echte Aliase — dieselbe Funktion, nur zweimal benannt. Die …Addr6-Form ist die von der Spezifikation vorgesehene.

Eigene und fremde Adresse abfragen

Signatur Beschreibung
SocketGetOwnAddr(fd: int64, addrBuf: int64, addrLen: int64): int64 lokale Adresse des Sockets; addrBuf muss SOCKADDR_IN_SIZE groß sein
SocketGetPeerAddr(fd: int64, addrBuf: int64, addrLen: int64): int64 Adresse der verbundenen Gegenstelle

Nützlich, wenn der Port vom Kernel vergeben wurde — nach einem Bind auf Port 0 steht die tatsächlich belegte Nummer erst hier.


Verbindungen annehmen: blockierend oder nicht

Signatur Beschreibung
AcceptBlocking(fd: int64, addrBuf: int64, addrLen: int64): int64 wartet, bis eine Verbindung vorliegt; setzt SOCK_CLOEXEC
AcceptNonBlocking(fd: int64, addrBuf: int64, addrLen: int64): int64 kehrt sofort zurück; setzt SOCK_NONBLOCK und SOCK_CLOEXEC

Beide liefern einen neuen Deskriptor. Liegt bei AcceptNonBlocking keine Verbindung an, ist das Ergebnis -11 (-EAGAIN) — das ist kein Fehler, sondern die übliche Antwort in einer Ereignisschleife (→ std.net.epoll).

Dass beide SOCK_CLOEXEC setzen, ist wichtiger als es aussieht: ohne dieses Flag erbt jeder mit fork/execve gestartete Kindprozess die offene Verbindung.


Mehrere Datagramme in einem Syscall

sendmmsg und recvmmsg übertragen mehrere Nachrichten mit einem einzigen Systemaufruf. Bei hohen Paketraten spart das den größten Einzelposten — den Wechsel in den Kernel und zurück.

Signatur Beschreibung
MmsgAlloc(vlen: int64, iovOut: int64): int64 legt vec- und iov-Feld für vlen Einträge an; liefert den vec-Zeiger, 0 bei Fehler
MmsgSetBuf(iov: int64, idx: int64, buf: int64, bufLen: int64) Datenpuffer für Eintrag idx eintragen
SendMmsg(fd: int64, vec: int64, vlen: int64, flags: int64): int64 bis zu vlen Nachrichten senden
RecvMmsg(fd: int64, vec: int64, vlen: int64, flags: int64): int64 bis zu vlen Nachrichten empfangen
MmsgGetLen(vec: int64, idx: int64): int64 empfangene Bytezahl aus mmsghdr[idx].msg_len
MmsgFree(vec: int64, iov: int64, vlen: int64) beide Felder freigeben

iovOut ist ein alloc(8)-Puffer, in den MmsgAlloc den iov-Zeiger schreibt — die Funktion gibt also zwei Zeiger zurück, einen über den Rückgabewert und einen über diesen Parameter. Beide werden für MmsgFree gebraucht.

Der Rückgabewert von SendMmsg/RecvMmsg ist die Zahl der tatsächlich übertragenen Nachrichten; sie kann kleiner als vlen sein.


Socket-Optionen: was sich mit #1611 geändert hat

<WRAP alert> Bis lyxc 1.1.1C lieferten alle zehn Options-Setter EFAULT zurück und wirkten nicht: optval wurde als Wert statt als Adresse an setsockopt übergeben, der Kernel las an Adresse 1 (#1611). Betroffen waren TCPConnSetNodelay, TCPConnSetKeepAlive, TCPConnSetRecvBuf, TCPConnSetSendBuf, TCPConnSetReuseAddr, TCPListenerSetReuseAddr, TCPListenerSetReusePort, UDPSocketSetReuseAddr, UDPSocketSetRecvBuf und UDPSocketSetSendBuf.

Schwerer wog der Lesepfad: TCPConnGetError und UDPSocketGetError lasen den Fehlerstand nie und meldeten deshalb immer 0 — „kein Fehler„. Im Connect-Pfad (revents & POLLOUT) galt eine Verbindung damit immer als erfolgreich, auch nach einem abgewiesenen Verbindungsversuch. </WRAP>

Beide Richtungen laufen jetzt über je einen Helfer, damit die Frage „Wert oder Adresse“ nur an einer Stelle beantwortet wird. Neu hinzugekommen ist UDPSocketSetBroadcast — die Option fehlte ganz, und ohne sie ist kein Rundruf möglich.

Zeitgrenzen für UDP

UDPSocketSetRecvTimeout(sock, sek, mikrosek) und UDPSocketSetSendTimeout(sock, sek, mikrosek) setzen SO_RCVTIMEO bzw. SO_SNDTIMEO; Rückgabe ist 0 bei Erfolg, sonst der negative Fehlercode. Läuft die Zeit ab, liefert UDPSocketRecv einen negativen Wert (EAGAIN), statt für immer zu blockieren.

Beide Setter brauchen eine timeval aus zwei 64-Bit-Werten — der Helfer für die einfachen int-Optionen schreibt nur vier Byte und taugt hier nicht. Eingezogen wurden sie für std.net.dns, wo eine ausbleibende Antwort den Aufrufer aufhängte (#1641).

UDPSocketSetRecvTimeout(sock, 2, 0);       // zwei Sekunden
var n: int64 := UDPSocketRecv(sock, buf, 512, 0, 0);
if (n < 0) { PrintLn("keine Antwort"); }

Letzte Aktualisierung: 2026-08-19 — UDPSocketSetRecvTimeout/UDPSocketSetSendTimeout ergänzt (#1641).

Vorherige Aktualisierung: 2026-08-18 — Options-Setter, Fehlerabfrage und UDPSocketSetBroadcast nachgezogen (#1611).