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)
| 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)
| 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)
| 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)
| 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 |
| 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)
| 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)
| 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).