class Socket
Die Klasse Socket bietet Zugriff auf die zugrundeliegenden betriebssystemspezifischen Socket-Implementierungen. Sie kann verwendet werden, um betriebssystemspezifischere Funktionalitäten bereitzustellen als die protokollspezifischen Socket-Klassen.
Die unter Socket::Constants definierten Konstanten sind auch unter Socket definiert. Beispielsweise ist Socket::AF_INET genauso verwendbar wie Socket::Constants::AF_INET. Eine Liste der Konstanten finden Sie unter Socket::Constants.
Was ist ein Socket?
Sockets sind Endpunkte eines bidirektionalen Kommunikationskanals. Sockets können innerhalb eines Prozesses, zwischen Prozessen auf derselben Maschine oder zwischen verschiedenen Maschinen kommunizieren. Es gibt viele Arten von Sockets: TCPSocket, UDPSocket oder UNIXSocket zum Beispiel.
Sockets haben ihre eigene Terminologie
domain: Die Familie der Protokolle
type: Der Typ der Kommunikation zwischen den beiden Endpunkten, typischerweise
protocol: Typischerweise null. Dies kann verwendet werden, um eine Variante eines Protokolls zu identifizieren.
hostname: Der Identifikator einer Netzwerkschnittstelle
-
ein String (Hostname, IPv4- oder IPv6-Adresse oder
broadcast, was eine Broadcast-Adresse angibt) -
ein String der Länge Null, der
INADDR_ANYangibt -
eine Ganzzahl (interpretiert als Binäradresse in Host-Byte-Reihenfolge).
Schnelleinstieg
Viele der Klassen, wie z. B. TCPSocket, UDPSocket oder UNIXSocket, vereinfachen die Verwendung von Sockets im Vergleich zur entsprechenden C-Programmierschnittstelle.
Erstellen wir einen Internet-Socket mit dem IPv4-Protokoll auf eine C-ähnliche Weise
require 'socket' s = Socket.new Socket::AF_INET, Socket::SOCK_STREAM s.connect Socket.pack_sockaddr_in(80, 'example.com')
Sie könnten auch die Klasse TCPSocket verwenden
s = TCPSocket.new 'example.com', 80
Ein einfacher Server könnte so aussehen
require 'socket' server = TCPServer.new 2000 # Server bound to port 2000 loop do client = server.accept # Wait for a client to connect client.puts "Hello !" client.puts "Time is #{Time.now}" client.close end
Ein einfacher Client könnte so aussehen
require 'socket' s = TCPSocket.new 'localhost', 2000 while line = s.gets # Read lines from socket puts line # and print them end s.close # close socket when done
Exception-Behandlung
Die Socket-Implementierung von Ruby löst Ausnahmen basierend auf dem vom systemabhängigen Implementierung generierten Fehler aus. Deshalb sind die Methoden so dokumentiert, dass sie Unix-basierte Systemausnahmen von Windows-basierten Ausnahmen trennen. Wenn weitere Informationen zu einer bestimmten Ausnahme benötigt werden, konsultieren Sie bitte die Unix-Manualpages oder die Windows WinSock-Referenz.
Bequeme Methoden
Obwohl der allgemeine Weg zur Erstellung von Sockets Socket.new ist, gibt es für die meisten Fälle mehrere Methoden zur Socket-Erstellung.
- TCP-Client-Socket
- TCP-Server-Socket
- UNIX-Client-Socket
- UNIX-Server-Socket
Dokumentation von
-
Zach Dennis
-
Sam Roberts
-
Programming Ruby von The Pragmatic Bookshelf.
Viele Materialien in dieser Dokumentation stammen mit Erlaubnis aus Programming Ruby von The Pragmatic Bookshelf.
Constants
- AF_ALG
-
Schnittstelle zur Kernel-Krypto-API
- AF_APPLETALK
-
AppleTalk-Protokoll
- AF_ATM
-
Asynchronous Transfer Mode
- AF_AX25
-
AX.25-Protokoll
- AF_BLUETOOTH
-
Low-Level-Socket-Protokoll für Bluetooth
- AF_CAN
-
Controller Area Network Automotive Bus Protokoll
- AF_CCITT
-
CCITT (jetzt ITU-T) Protokolle
- AF_CHAOS
-
MIT CHAOS Protokolle
- AF_CNT
-
Computer Network Technology
- AF_COIP
-
Verbindungsorientiertes IP
- AF_DATAKIT
-
Datakit-Protokoll
- AF_DEC
-
DECnet-Protokoll
- AF_DECnet
-
DECnet-Protokoll
- AF_DLI
-
DEC Direct Data Link Interface Protokoll
- AF_E164
-
CCITT (ITU-T) E.164 Empfehlung
- AF_ECMA
-
European Computer Manufacturers Protokolle
- AF_HYLINK
-
NSC Hyperchannel-Protokoll
- AF_IB
-
Native Adressierung von InfiniBand
- AF_IMPLINK
-
ARPANET IMP Protokoll
- AF_INET
-
IPv4-Protokoll
- AF_INET6
-
IPv6-Protokoll
- AF_IPX
-
IPX-Protokoll
- AF_ISDN
-
Integrated Services Digital Network
- AF_ISO
-
ISO Open Systems Interconnection Protokolle
- AF_KCM
-
KCM (Kernel Connection Multiplexor) Schnittstelle
- AF_KEY
-
Schlüsselverwaltungsprotokoll, ursprünglich für die Verwendung mit IPsec entwickelt
- AF_LAT
-
Local Area Transport Protokoll
- AF_LINK
-
Link-Layer-Schnittstelle
- AF_LLC
-
Logical Link Control (IEEE 802.2 LLC) Protokoll
- AF_LOCAL
-
Host-interne Protokolle
- AF_MAX
-
Maximale Adressfamilie für diese Plattform
- AF_MPLS
-
Multiprotocol Label Switching
- AF_NATM
-
Native ATM-Zugriff
- AF_NDRV
-
Rohzugriff auf Netzwerktreiber
- AF_NETBIOS
-
NetBIOS
- AF_NETGRAPH
-
Netgraph-Sockets
- AF_NETLINK
-
Kernel-Benutzer-Schnittstelle für Geräte
- AF_NS
-
XEROX NS Protokolle
- AF_OSI
-
ISO Open Systems Interconnection Protokolle
- AF_PACKET
-
Direkter Zugriff auf die Link-Schicht
- AF_PPP
-
Point-to-Point Protocol
- AF_PPPOX
-
Generische PPP-Transportschicht zur Einrichtung von L2-Tunneln (L2TP und PPPoE)
- AF_PUP
-
PARC Universal Packet Protocol
- AF_RDS
-
Reliable Datagram Sockets (RDS) Protokoll
- AF_ROUTE
-
Internes Routing-Protokoll
- AF_SIP
-
Simple Internet Protocol
- AF_SNA
-
IBM SNA-Protokoll
- AF_SYSTEM
-
Kernel-Ereignisnachrichten
- AF_TIPC
-
TIPC, "Cluster Domain Sockets" Protokoll
- AF_UNIX
-
UNIX-Sockets
- AF_UNSPEC
-
Nicht spezifiziertes Protokoll, jede unterstützte Adressfamilie
- AF_VSOCK
-
VSOCK (ursprünglich "VMWare VSockets") Protokoll für die Kommunikation zwischen Hypervisor und Gast
- AF_XDP
-
XDP (Express Data Path) Schnittstelle
- AI_ADDRCONFIG
-
Nur akzeptieren, wenn eine Adresse zugewiesen ist
- AI_ALL
-
Alle Adressen zulassen
- AI_CANONNAME
-
Den kanonischen Namen füllen
- AI_DEFAULT
-
Standard-Flags für getaddrinfo
- AI_MASK
-
Gültige Flag-Maske für getaddrinfo (nicht für die Anwendung)
- AI_NUMERICHOST
-
Host-Namensauflösung verhindern
- AI_NUMERICSERV
-
Service-Namensauflösung verhindern
- AI_PASSIVE
-
Adresse für die Verwendung mit bind() erhalten
- AI_V4MAPPED
-
IPv4-gemappte IPv6-Adressen akzeptieren
- AI_V4MAPPED_CFG
-
IPv4-gemappte Adressen akzeptieren, wenn der Kernel dies unterstützt
- EAI_ADDRFAMILY
-
Adressfamilie für Hostnamen wird nicht unterstützt
- EAI_AGAIN
-
Temporärer Fehler bei der Namensauflösung
- EAI_BADFLAGS
-
Ungültige Flags
- EAI_BADHINTS
-
Ungültiger Wert für Hints
- EAI_FAIL
-
Nicht behebbarer Fehler bei der Namensauflösung
- EAI_FAMILY
-
Adressfamilie wird nicht unterstützt
- EAI_MAX
-
Maximaler Fehlercode von getaddrinfo
- EAI_MEMORY
-
Speicherzuweisungsfehler
- EAI_NODATA
-
Keine Adresse mit Hostnamen assoziiert
- EAI_NONAME
-
Hostname oder Servname nicht vorhanden oder unbekannt
- EAI_OVERFLOW
-
Argumentpufferüberlauf
- EAI_PROTOCOL
-
Aufgelöstes Protokoll ist unbekannt
- EAI_SERVICE
-
Servname wird für diesen Socket-Typ nicht unterstützt
- EAI_SOCKTYPE
-
Socket-Typ wird nicht unterstützt
- EAI_SYSTEM
-
Systemfehler in errno zurückgegeben
- IFF_802_1Q_VLAN
-
802.1Q VLAN-Gerät
- IFF_ALLMULTI
-
Alle Multicast-Pakete empfangen
- IFF_ALTPHYS
-
alternative physische Verbindung verwenden
- IFF_AUTOMEDIA
-
automatische Medienauswahl aktiv
- IFF_BONDING
-
Bonding-Master oder -Slave
- IFF_BRIDGE_PORT
-
Als Bridge-Port verwendetes Gerät
- IFF_BROADCAST
-
Broadcast-Adresse gültig
- IFF_CANTCHANGE
-
Flags nicht änderbar
- IFF_CANTCONFIG
-
nicht konfigurierbar mit ioctl(2)
- IFF_DEBUG
-
Debugging einschalten
- IFF_DISABLE_NETPOLL
-
Netpoll zur Laufzeit deaktivieren
- IFF_DONT_BRIDGE
-
Bridging dieses Ethernet-Geräts nicht zulassen
- IFF_DORMANT
-
Treiber meldet "dormant" (ruhend)
- IFF_DRV_OACTIVE
-
TX-Hardware-Warteschlange ist voll
- IFF_DRV_RUNNING
-
Ressourcen zugewiesen
- IFF_DYING
-
Schnittstelle wird heruntergefahren
- IFF_DYNAMIC
-
Dialup-Gerät mit sich ändernden Adressen
- IFF_EBRIDGE
-
Ethernet-Bridging-Gerät
- IFF_ECHO
-
gesendete Pakete echoen
- IFF_ISATAP
-
ISATAP-Schnittstelle (RFC4214)
- IFF_LINK0
-
Link-Layer-definiertes Bit 0
- IFF_LINK1
-
Link-Layer-definiertes Bit 1
- IFF_LINK2
-
Link-Layer-definiertes Bit 2
- IFF_LIVE_ADDR_CHANGE
-
Hardware-Adressänderung im laufenden Betrieb
- IFF_LOOPBACK
-
Loopback-Netzwerk
- IFF_LOWER_UP
-
Treiber meldet L1 Up
- IFF_MACVLAN_PORT
-
Als MacVLAN-Port verwendetes Gerät
- IFF_MASTER
-
Master einer Lastverteilung
- IFF_MASTER_8023AD
-
Bonding-Master, 802.3ad.
- IFF_MASTER_ALB
-
Bonding-Master, balance-alb.
- IFF_MASTER_ARPMON
-
Bonding-Master, ARP-Monitor in Verwendung
- IFF_MONITOR
-
Benutzer angeforderter Monitor-Modus
- IFF_MULTICAST
-
Multicast-fähig
- IFF_NOARP
-
Kein Address Resolution Protocol
- IFF_NOTRAILERS
-
Vermeide die Verwendung von Trailers
- IFF_OACTIVE
-
Übertragung läuft
- IFF_OVS_DATAPATH
-
Gerät als Open vSwitch-Datapath-Port verwendet
- IFF_POINTOPOINT
-
Punkt-zu-Punkt-Verbindung
- IFF_PORTSEL
-
Medientyp einstellbar
- IFF_PPROMISC
-
Benutzer angeforderter Promiscuous-Modus
- IFF_PROMISC
-
Alle Pakete empfangen
- IFF_RENAMING
-
Schnittstelle wird umbenannt
- IFF_ROUTE
-
Routing-Eintrag installiert
- IFF_RUNNING
-
Ressourcen zugewiesen
- IFF_SIMPLEX
-
eigene Übertragungen nicht hörbar
- IFF_SLAVE
-
Slave einer Lastverteilung
- IFF_SLAVE_INACTIVE
-
Bonding-Slave nicht der aktuell aktive
- IFF_SLAVE_NEEDARP
-
benötigt ARPs zur Validierung
- IFF_SMART
-
Schnittstelle verwaltet eigene Routen
- IFF_STATICARP
-
statisches ARP
- IFF_SUPP_NOFCS
-
sendet benutzerdefinierte FCS
- IFF_TEAM_PORT
-
als Team-Port verwendet
- IFF_TX_SKB_SHARING
-
teilen von SKBs bei der Übertragung
- IFF_UNICAST_FLT
-
Unicast-Filterung
- IFF_UP
-
Schnittstelle ist aktiv
- IFF_VOLATILE
-
volatile Flags
- IFF_WAN_HDLC
-
WAN HDLC-Gerät
- IFF_XMIT_DST_RELEASE
-
dev_hard_start_xmit() darf skb->dst freigeben
- IFNAMSIZ
-
Maximale Größe des Schnittstellennamens
- IF_NAMESIZE
-
Maximale Größe des Schnittstellennamens
- INADDR_ALLHOSTS_GROUP
-
Multicast-Gruppe für alle Systeme in diesem Subset
- INADDR_ANY
-
Ein an
INADDR_ANYgebundener Socket empfängt Pakete von allen Schnittstellen und sendet von der Standard-IP-Adresse - INADDR_BROADCAST
-
Die Broadcast-Adresse des Netzwerks
- INADDR_LOOPBACK
-
Die Loopback-Adresse
- INADDR_MAX_LOCAL_GROUP
-
Die letzte lokale Netzwerk-Multicast-Gruppe
- INADDR_NONE
-
Eine Bitmaske für den Abgleich keiner gültigen IP-Adresse
- INADDR_UNSPEC_GROUP
-
Die reservierte Multicast-Gruppe
- INET6_ADDRSTRLEN
-
Maximale Länge einer IPv6-Adresszeichenkette
- INET_ADDRSTRLEN
-
Maximale Länge einer IPv4-Adresszeichenkette
- IPPORT_RESERVED
-
Standard-Mindestadresse für bind oder connect
- IPPORT_USERRESERVED
-
Standard-Maximaladresse für bind oder connect
- IPPROTO_AH
-
IP6-Authentifizierungsheader
- IPPROTO_BIP
- IPPROTO_DSTOPTS
-
IP6-Zieloption
- IPPROTO_EGP
-
Exterior Gateway Protocol
- IPPROTO_EON
-
ISO cnlp
- IPPROTO_ESP
-
IP6 Encapsulated Security Payload
- IPPROTO_FRAGMENT
-
IP6-Fragmentierungsheader
- IPPROTO_GGP
-
Gateway-zu-Gateway-Protokoll
- IPPROTO_HELLO
-
Routing-Protokoll "hello"
- IPPROTO_HOPOPTS
-
IP6 Hop-by-Hop-Optionen
- IPPROTO_ICMP
-
Control Message Protocol
- IPPROTO_ICMPV6
-
ICMP6
- IPPROTO_IDP
-
XNS IDP
- IPPROTO_IGMP
-
Group Management Protocol
- IPPROTO_IP
-
Dummy-Protokoll für IP
- IPPROTO_IPV6
-
IP6-Header
- IPPROTO_MAX
-
Maximale IPPROTO-Konstante
- IPPROTO_ND
-
Sun Net Disk-Protokoll
- IPPROTO_NONE
-
IP6 kein nächster Header
- IPPROTO_PUP
-
PARC Universal Packet Protocol
- IPPROTO_RAW
-
Roh-IP-Paket
- IPPROTO_ROUTING
-
IP6-Routing-Header
- IPPROTO_TCP
-
TCP
- IPPROTO_TP
-
ISO Transportprotokoll Klasse 4
- IPPROTO_UDP
-
UDP
- IPPROTO_XTP
-
Xpress Transport Protocol
- IPV6_CHECKSUM
-
Checksummenversatz für Roh-Sockets
- IPV6_DONTFRAG
-
Pakete nicht fragmentieren
- IPV6_DSTOPTS
-
Zieloption
- IPV6_HOPLIMIT
-
Hop-Limit
- IPV6_HOPOPTS
-
Hop-by-Hop-Option
- IPV6_JOIN_GROUP
-
Mitgliedschaft einer Gruppe beitreten
- IPV6_LEAVE_GROUP
-
Mitgliedschaft einer Gruppe verlassen
- IPV6_MTU_DISCOVER
-
Pfad-MTU-Erkennung
- IPV6_MULTICAST_HOPS
-
IP6-Multicast-Hops
- IPV6_MULTICAST_IF
-
IP6-Multicast-Schnittstelle
- IPV6_MULTICAST_LOOP
-
IP6-Multicast-Loopback
- IPV6_NEXTHOP
-
Nächste Hop-Adresse
- IPV6_PATHMTU
-
Aktuelle Pfad-MTU abrufen
- IPV6_PKTINFO
-
Paketinformationen mit Datagramm empfangen
- IPV6_RECVDSTOPTS
-
Alle IP6-Optionen für die Antwort empfangen
- IPV6_RECVERR
-
Erweiterte zuverlässige Fehlerberichterstattung aktivieren
- IPV6_RECVHOPLIMIT
-
Hop-Limit mit Datagramm empfangen
- IPV6_RECVHOPOPTS
-
Hop-by-Hop-Optionen empfangen
- IPV6_RECVPATHMTU
-
Aktuelle Pfad-MTU mit Datagramm empfangen
- IPV6_RECVPKTINFO
-
Ziel-IP-Adresse und eingehende Schnittstelle empfangen
- IPV6_RECVRTHDR
-
Routing-Header empfangen
- IPV6_RECVTCLASS
-
Klassen für den Datenverkehr empfangen
- IPV6_RTHDR
-
Ermöglicht das Entfernen von festen Routing-Headern
- IPV6_RTHDRDSTOPTS
-
Ermöglicht das Entfernen von festen Zieloptionsheadern
- IPV6_RTHDR_TYPE_0
-
Routing-Header-Typ 0
- IPV6_TCLASS
-
Klasse für den Datenverkehr angeben
- IPV6_UNICAST_HOPS
-
IP6-Unicast-Hops
- IPV6_USE_MIN_MTU
-
Die minimale MTU-Größe verwenden
- IPV6_V6ONLY
-
Nur IPv6 mit einem Wildcard-Bind binden
- IPX_TYPE
- IP_ADD_MEMBERSHIP
-
Mitgliedschaft einer Multicast-Gruppe hinzufügen
- IP_ADD_SOURCE_MEMBERSHIP
-
Mitgliedschaft einer Multicast-Gruppe hinzufügen
- IP_BLOCK_SOURCE
-
IPv4-Multicast-Pakete von einer bestimmten Quelladresse blockieren
- IP_DEFAULT_MULTICAST_LOOP
-
Standard-Multicast-Loopback
- IP_DEFAULT_MULTICAST_TTL
-
Standard-Multicast-TTL
- IP_DONTFRAG
-
Pakete nicht fragmentieren
- IP_DROP_MEMBERSHIP
-
Mitgliedschaft einer Multicast-Gruppe entfernen
- IP_DROP_SOURCE_MEMBERSHIP
-
Mitgliedschaft einer Multicast-Gruppe entfernen
- IP_FREEBIND
-
Das Binden an nicht existierende IP-Adressen erlauben
- IP_HDRINCL
-
Header wird mit Daten eingeschlossen
- IP_IPSEC_POLICY
-
IPsec-Sicherheitsrichtlinie
- IP_MAX_MEMBERSHIPS
-
Maximale Anzahl von Multicast-Gruppen, denen ein Socket beitreten kann
- IP_MINTTL
-
Minimale TTL für empfangene Pakete
- IP_MSFILTER
-
Multicast-Quellenfilterung
- IP_MTU
-
Die maximale Übertragungseinheit (MTU) des Sockets
- IP_MTU_DISCOVER
-
Pfad-MTU-Erkennung
- IP_MULTICAST_IF
-
IP-Multicast-Schnittstelle
- IP_MULTICAST_LOOP
-
IP-Multicast-Loopback
- IP_MULTICAST_TTL
-
IP-Multicast-TTL
- IP_ONESBCAST
-
Ausgehende Broadcast-Datagramme zwingen, die undirektionierte Broadcast-Adresse zu haben
- IP_OPTIONS
-
IP-Optionen, die in Pakete eingeschlossen werden sollen
- IP_PASSSEC
-
Sicherheitskontext mit Datagramm abrufen
- IP_PKTINFO
-
Paketinformationen mit Datagrammen empfangen
- IP_PKTOPTIONS
-
Paketoptionen mit Datagrammen empfangen
- IP_PMTUDISC_DO
-
Immer DF-Frames senden
- IP_PMTUDISC_DONT
-
Niemals DF-Frames senden
- IP_PMTUDISC_WANT
-
Pro-Route-Hinweise verwenden
- IP_PORTRANGE
-
Den Portbereich für Sockets mit nicht spezifizierten Portnummern festlegen
- IP_RECVDSTADDR
-
IP-Zieladresse mit Datagramm empfangen
- IP_RECVERR
-
Erweiterte zuverlässige Fehlerberichterstattung aktivieren
- IP_RECVIF
-
Schnittstelleninformationen mit Datagrammen empfangen
- IP_RECVOPTS
-
Alle IP-Optionen mit Datagramm empfangen
- IP_RECVRETOPTS
-
Alle IP-Optionen für die Antwort empfangen
- IP_RECVSLLA
-
Link-Layer-Adresse mit Datagrammen empfangen
- IP_RECVTOS
-
TOS (Type of Service) mit eingehenden Paketen empfangen
- IP_RECVTTL
-
IP-TTL (Time To Live) mit Datagrammen empfangen
- IP_RETOPTS
-
IP-Optionen, die in Datagrammen eingeschlossen werden sollen
- IP_ROUTER_ALERT
-
Durchlauf-Router benachrichtigen, den Inhalt eines IP-Pakets genauer zu prüfen
- IP_SENDSRCADDR
-
Quelladresse für ausgehende UDP-Datagramme
- IP_TOS
-
IP-Type-of-Service
- IP_TRANSPARENT
-
Transparenter Proxy
- IP_TTL
-
IP-Time-to-Live
- IP_UNBLOCK_SOURCE
-
IPv4-Multicast-Pakete von einer bestimmten Quelladresse entblockieren
- IP_XFRM_POLICY
- LOCAL_CONNWAIT
-
Verbindung blockiert, bis sie akzeptiert wird
- LOCAL_CREDS
-
Übermittelt Anmeldeinformationen an den Empfänger
- LOCAL_PEERCRED
-
Peer-Anmeldeinformationen abrufen
- MCAST_BLOCK_SOURCE
-
Multicast-Pakete von dieser Quelle blockieren
- MCAST_EXCLUDE
-
Exklusiver Multicast-Quellenfilter
- MCAST_INCLUDE
-
Inklusiver Multicast-Quellenfilter
- MCAST_JOIN_GROUP
-
Einer Multicast-Gruppe beitreten
- MCAST_JOIN_SOURCE_GROUP
-
Einer Multicast-Quellgruppe beitreten
- MCAST_LEAVE_GROUP
-
Eine Multicast-Gruppe verlassen
- MCAST_LEAVE_SOURCE_GROUP
-
Eine Multicast-Quellgruppe verlassen
- MCAST_MSFILTER
-
Multicast-Quellenfilterung
- MCAST_UNBLOCK_SOURCE
-
Multicast-Pakete von dieser Quelle entblockieren
- MSG_COMPAT
-
Ende des Datensatzes
- MSG_CONFIRM
-
Pfadgültigkeit bestätigen
- MSG_CTRUNC
-
Steuerdaten vor der Zustellung verloren gegangen
- MSG_DONTROUTE
-
Senden ohne Verwendung der Routing-Tabellen
- MSG_DONTWAIT
-
Diese Nachricht sollte nicht blockierend sein
- MSG_EOF
-
Daten vervollständigen die Verbindung
- MSG_EOR
-
Daten vervollständigen den Datensatz
- MSG_ERRQUEUE
-
Nachricht aus der Fehlerwarteschlange abrufen
- MSG_FASTOPEN
-
Schritt des Handshake-Prozesses reduzieren
- MSG_FIN
- MSG_FLUSH
-
Beginn einer Hold-Sequenz. Dumps nach so_temp
- MSG_HAVEMORE
-
Daten zum Lesen bereit
- MSG_HOLD
-
Fragment in so_temp halten
- MSG_MORE
-
Sender wird mehr senden
- MSG_NOSIGNAL
-
Kein SIGPIPE generieren
- MSG_OOB
-
Out-of-Band-Daten verarbeiten
- MSG_PEEK
-
Eingehende Nachricht ansehen
- MSG_PROXY
-
Auf vollständige Anfrage warten
- MSG_RCVMORE
-
Daten verbleiben im aktuellen Paket
- MSG_RST
- MSG_SEND
-
Paket in so_temp senden
- MSG_SYN
- MSG_TRUNC
-
Daten vor der Zustellung verworfen
- MSG_WAITALL
-
Auf vollständige Anfrage oder Fehler warten
- NI_DGRAM
-
Der spezifizierte Dienst ist ein Datagramm-Dienst (sucht UDP-Ports)
- NI_MAXHOST
-
Maximale Länge eines Hostnamens
- NI_MAXSERV
-
Maximale Länge eines Servicenamens
- NI_NAMEREQD
-
Ein Name ist erforderlich
- NI_NOFQDN
-
Für lokale Hosts ist kein FQDN erforderlich, nur der lokale Teil wird zurückgegeben
- NI_NUMERICHOST
-
Numerische Adresse zurückgeben
- NI_NUMERICSERV
-
Servicename als Ziffernzeichenkette zurückgeben
- PF_ALG
-
Schnittstelle zur Kernel-Krypto-API
- PF_APPLETALK
-
AppleTalk-Protokoll
- PF_ATM
-
Asynchronous Transfer Mode
- PF_AX25
-
AX.25-Protokoll
- PF_BLUETOOTH
-
Low-Level-Socket-Protokoll für Bluetooth
- PF_CAN
-
Controller Area Network Automotive Bus Protokoll
- PF_CCITT
-
CCITT (jetzt ITU-T) Protokolle
- PF_CHAOS
-
MIT CHAOS Protokolle
- PF_CNT
-
Computer Network Technology
- PF_COIP
-
Verbindungsorientiertes IP
- PF_DATAKIT
-
Datakit-Protokoll
- PF_DEC
-
DECnet-Protokoll
- PF_DECnet
-
DECnet-Protokoll
- PF_DLI
-
DEC Direct Data Link Interface Protokoll
- PF_ECMA
-
European Computer Manufacturers Protokolle
- PF_HYLINK
-
NSC Hyperchannel-Protokoll
- PF_IB
-
Native Adressierung von InfiniBand
- PF_IMPLINK
-
ARPANET IMP Protokoll
- PF_INET
-
IPv4-Protokoll
- PF_INET6
-
IPv6-Protokoll
- PF_IPX
-
IPX-Protokoll
- PF_ISDN
-
Integrated Services Digital Network
- PF_ISO
-
ISO Open Systems Interconnection Protokolle
- PF_KCM
-
KCM (Kernel Connection Multiplexor) Schnittstelle
- PF_KEY
-
Schlüsselverwaltungsprotokoll, ursprünglich für die Verwendung mit IPsec entwickelt
- PF_LAT
-
Local Area Transport Protokoll
- PF_LINK
-
Link-Layer-Schnittstelle
- PF_LLC
-
Logical Link Control (IEEE 802.2 LLC) Protokoll
- PF_LOCAL
-
Host-interne Protokolle
- PF_MAX
-
Maximale Adressfamilie für diese Plattform
- PF_MPLS
-
Multiprotocol Label Switching
- PF_NATM
-
Native ATM-Zugriff
- PF_NDRV
-
Rohzugriff auf Netzwerktreiber
- PF_NETBIOS
-
NetBIOS
- PF_NETGRAPH
-
Netgraph-Sockets
- PF_NETLINK
-
Kernel-Benutzer-Schnittstelle für Geräte
- PF_NS
-
XEROX NS Protokolle
- PF_OSI
-
ISO Open Systems Interconnection Protokolle
- PF_PACKET
-
Direkter Zugriff auf die Link-Schicht
- PF_PIP
-
Hilft bei der Identifizierung von PIP-Paketen
- PF_PPP
-
Point-to-Point Protocol
- PF_PPPOX
-
Generische PPP-Transportschicht zur Einrichtung von L2-Tunneln (L2TP und PPPoE)
- PF_PUP
-
PARC Universal Packet Protocol
- PF_RDS
-
Reliable Datagram Sockets (RDS) Protokoll
- PF_ROUTE
-
Internes Routing-Protokoll
- PF_RTIP
-
Hilft bei der Identifizierung von RTIP-Paketen
- PF_SIP
-
Simple Internet Protocol
- PF_SNA
-
IBM SNA-Protokoll
- PF_SYSTEM
-
Kernel-Ereignisnachrichten
- PF_TIPC
-
TIPC, "Cluster Domain Sockets" Protokoll
- PF_UNIX
-
UNIX-Sockets
- PF_UNSPEC
-
Nicht spezifiziertes Protokoll, jede unterstützte Adressfamilie
- PF_VSOCK
-
VSOCK (ursprünglich "VMWare VSockets") Protokoll für die Kommunikation zwischen Hypervisor und Gast
- PF_XDP
-
XDP (Express Data Path) Schnittstelle
- PF_XTP
-
eXpress Transfer Protocol
- SCM_BINTIME
-
Zeitstempel (bintime)
- SCM_CREDENTIALS
-
Die Anmeldeinformationen des Senders
- SCM_CREDS
-
Prozess-Anmeldeinformationen
- SCM_RIGHTS
-
Zugriffsrechte
- SCM_TIMESTAMP
-
Zeitstempel (timeval)
- SCM_TIMESTAMPING
-
Zeitstempel (timespec-Liste) (Linux 2.6.30)
- SCM_TIMESTAMPNS
-
Timespec (timespec)
- SCM_UCRED
-
Benutzer-Anmeldeinformationen
- SCM_WIFI_STATUS
-
Wifi-Status (Linux 3.3)
- SHUT_RD
-
Lese-Seite des Sockets schließen
- SHUT_RDWR
-
Beide Seiten des Sockets schließen
- SHUT_WR
-
Schreib-Seite des Sockets schließen
- SOCK_CLOEXEC
-
Setzt das "close-on-exec" (FD_CLOEXEC) Flag auf dem neuen Dateideskriptor.
- SOCK_DGRAM
-
Ein Datagramm-Socket bietet verbindungslose, unzuverlässige Nachrichtenübermittlung
- SOCK_NONBLOCK
-
Setzt das Dateistatusflag O_NONBLOCK auf der offenen Datei-Beschreibung (siehe open(2)), auf die sich der neue Dateideskriptor bezieht.
- SOCK_PACKET
-
Geräte-Level-Paket-Zugriff
- SOCK_RAW
-
Ein Roh-Socket bietet Low-Level-Zugriff für direkten Zugriff oder die Implementierung von Netzwerkprotokollen
- SOCK_RDM
-
Ein zuverlässiger Datagramm-Socket bietet zuverlässige Zustellung von Nachrichten
- SOCK_SEQPACKET
-
Ein sequenzieller Paket-Socket bietet eine sequenzierte, zuverlässige bidirektionale Verbindung für Datagramme
- SOCK_STREAM
-
Ein Stream-Socket bietet eine sequenzierte, zuverlässige bidirektionale Verbindung für einen Byte-Stream
- SOL_ATALK
-
AppleTalk Socket-Optionen
- SOL_AX25
-
AX.25 Socket-Optionen
- SOL_IP
-
IP Socket-Optionen
- SOL_IPX
-
IPX Socket-Optionen
- SOL_SOCKET
-
Socket-Level-Optionen
- SOL_TCP
-
TCP Socket-Optionen
- SOL_UDP
-
UDP Socket-Optionen
- SOMAXCONN
-
Maximale Anzahl von Verbindungsanfragen, die für einen Socket in die Warteschlange gestellt werden können
- SOPRI_BACKGROUND
-
Hintergrund-Socket-Priorität
- SOPRI_INTERACTIVE
-
Interaktive Socket-Priorität
- SOPRI_NORMAL
-
Normale Socket-Priorität
- SO_ACCEPTCONN
-
Auf dem Socket wurde listen() aufgerufen
- SO_ACCEPTFILTER
-
Es ist ein Akzeptanzfilter vorhanden
- SO_ALLZONES
-
Zonengrenzen umgehen
- SO_ATTACH_FILTER
-
Einen Akzeptanzfilter anhängen
- SO_BINDTODEVICE
-
Nur Pakete von dem angegebenen Interface senden
- SO_BINTIME
-
Zeitstempel mit Datagrammen empfangen (bintime)
- SO_BPF_EXTENSIONS
-
Unterstützte BPF-Erweiterungen abfragen (Linux 3.14)
- SO_BROADCAST
-
Senden von Broadcast-Nachrichten zulassen
- SO_BUSY_POLL
-
Schwellenwert in Mikrosekunden für Low-Latency-Polling setzen (Linux 3.11)
- SO_CONNECT_TIME
-
Gibt die Anzahl der Sekunden zurück, die ein Socket verbunden war. Diese Option ist nur für verbindungsorientierte Protokolle gültig (Windows)
- SO_DEBUG
-
Debugging-Informationen aufzeichnen
- SO_DETACH_FILTER
-
Einen Akzeptanzfilter abtrennen
- SO_DOMAIN
-
Für socket() angegebene Domäne (Linux 2.6.32)
- SO_DONTROUTE
-
Interface-Adressen verwenden
- SO_DONTTRUNC
-
Ungelesene Daten beibehalten
- SO_ERROR
-
Fehlerstatus abrufen und löschen
- SO_GET_FILTER
-
Filter erhalten, der von
SO_ATTACH_FILTERgesetzt wurde (Linux 3.8) - SO_INCOMING_CPU
-
Empfängt die CPU, die dem Socket zugeordnet ist (Linux 3.19)
- SO_INCOMING_NAPI_ID
-
Empfängt die NAPI-ID, die einer RX-Warteschlange zugeordnet ist (Linux 4.12)
- SO_KEEPALIVE
-
Verbindungen am Leben halten
- SO_LINGER
-
Linger beim Schließen, wenn Daten vorhanden sind
- SO_LOCK_FILTER
-
Filter sperren, der an einen Socket angehängt ist (Linux 3.9)
- SO_MAC_EXEMPT
-
Zwanghafte Zugriffskontrolle-Ausnahme für unbeschriftete Peers
- SO_MARK
-
Markierung für Routing basierend auf Markierungen setzen (Linux 2.6.25)
- SO_MAX_PACING_RATE
-
Begrenzt die vom Transportschicht berechnete Rate. [Bytes pro Sekunde] (Linux 3.13)
- SO_NKE
-
Socket-Level Network Kernel Extension installieren
- SO_NOFCS
-
Setzt den Netns eines Sockets (Linux 3.4)
- SO_NOSIGPIPE
-
Kein SIGPIPE bei EPIPE
- SO_NO_CHECK
-
Checksummen deaktivieren
- SO_NREAD
-
Anzahl der Bytes im ersten Paket abrufen
- SO_OOBINLINE
-
Empfangene Out-of-Band-Daten inline belassen
- SO_PASSCRED
-
Empfängt
SCM_CREDENTIALSNachrichten - SO_PASSSEC
-
Übergabe des Sicherheitskontexts umschalten (Linux 2.6.18)
- SO_PEEK_OFF
-
Peek-Offset setzen (Linux 3.4)
- SO_PEERCRED
-
Die Anmeldeinformationen des fremden Prozesses, der mit diesem Socket verbunden ist
- SO_PEERNAME
-
Name des verbindenden Benutzers
- SO_PEERSEC
-
Sicherheitsanmeldeinformationen abrufen (Linux 2.6.2)
- SO_PRIORITY
-
Die protokollspezifische Priorität für alle Pakete auf diesem Socket
- SO_PROTOCOL
-
Für socket() angegebenes Protokoll (Linux 2.6.32)
- SO_RCVBUF
-
Empfangspuffergröße
- SO_RCVBUFFORCE
-
Empfangspuffergröße ohne rmem_max-Limit (Linux 2.6.14)
- SO_RCVLOWAT
-
Empfangs-Low-Water-Marke
- SO_RCVTIMEO
-
Empfang-Timeout
- SO_RECVUCRED
-
Empfange Benutzeranmeldeinformationen mit Datagramm
- SO_REUSEADDR
-
Lokale Adresswiederverwendung zulassen
- SO_REUSEPORT
-
Lokale Adress- und Portwiederverwendung zulassen
- SO_RTABLE
-
Routing-Tabelle für diesen Socket festlegen (OpenBSD)
- SO_RXQ_OVFL
-
Schalter für die Anzahl der verworfenen Pakete (Linux 2.6.33)
- SO_SECURITY_AUTHENTICATION
- SO_SECURITY_ENCRYPTION_NETWORK
- SO_SECURITY_ENCRYPTION_TRANSPORT
- SO_SELECT_ERR_QUEUE
-
select() soll Socket-Fehlerwarteschlange mit errorfds erkennen (Linux 3.10)
- SO_SETFIB
-
Zugehörige Routing-Tabelle für den Socket festlegen (FreeBSD)
- SO_SNDBUF
-
Größe des Sendepuffers
- SO_SNDBUFFORCE
-
Größe des Sendepuffers ohne wmem_max-Limit (Linux 2.6.14)
- SO_SNDLOWAT
-
Send-Low-Water-Mark
- SO_SNDTIMEO
-
Sende-Timeout
- SO_TIMESTAMP
-
Zeitstempel mit Datagrammen empfangen (timeval)
- SO_TIMESTAMPING
-
Zeitstempelung von eingehenden und ausgehenden Paketen (Linux 2.6.30)
- SO_TIMESTAMPNS
-
Nanosekunden-Zeitstempel mit Datagrammen empfangen (timespec)
- SO_TYPE
-
Socket-Typ abrufen
- SO_USELOOPBACK
-
Hardware umgehen, wenn möglich
- SO_USER_COOKIE
-
Festlegen einer Kennung hauptsächlich für ipfw-Zwecke
- SO_WANTMORE
-
Hinweis geben, wenn mehr Daten bereitstehen
- SO_WANTOOBFLAG
-
OOB-Daten werden im MSG_FLAG beim Empfang gewünscht
- SO_WIFI_STATUS
-
Schalter für WLAN-Status (Linux 3.3)
- TCP_CONGESTION
-
TCP-Stau-Kontrollalgorithmus (Linux 2.6.13, glibc 2.6)
- TCP_CONNECTION_INFO
-
Informationen über diesen Socket abrufen (macOS)
- TCP_COOKIE_TRANSACTIONS
-
TCP-Cookie-Transaktionen (Linux 2.6.33, glibc 2.18)
- TCP_CORK
-
Keine teilweise Frames senden (Linux 2.2, glibc 2.2)
- TCP_DEFER_ACCEPT
-
Einen lauschenden Socket erst benachrichtigen, wenn Daten bereitstehen (Linux 2.4, glibc 2.2)
- TCP_FASTOPEN
-
Schritt des Handshake-Prozesses reduzieren (Linux 3.7, glibc 2.18)
- TCP_INFO
-
Informationen über diesen Socket abrufen (Linux 2.4, glibc 2.2)
- TCP_KEEPALIVE
-
Leerlaufzeit, bevor Keepalive-Sonden gesendet werden (macOS)
- TCP_KEEPCNT
-
Maximale Anzahl von erlaubten Keepalive-Sonden, bevor eine Verbindung getrennt wird (Linux 2.4, glibc 2.2)
- TCP_KEEPIDLE
-
Leerlaufzeit, bevor Keepalive-Sonden gesendet werden (Linux 2.4, glibc 2.2)
- TCP_KEEPINTVL
-
Zeit zwischen Keepalive-Sonden (Linux 2.4, glibc 2.2)
- TCP_LINGER2
-
Lebensdauer von verwaisten FIN_WAIT2-Sockets (Linux 2.4, glibc 2.2)
- TCP_MAXSEG
-
Maximale Segmentgröße festlegen
- TCP_MD5SIG
-
MD5-Digests verwenden (RFC2385, Linux 2.6.20, glibc 2.7)
- TCP_NODELAY
-
Das Senden nicht verzögern, um Pakete zu bündeln
- TCP_NOOPT
-
Keine TCP-Optionen verwenden
- TCP_NOPUSH
-
Den letzten Schreibblock nicht pushen
- TCP_QUEUE_SEQ
-
Sequenz einer Warteschlange für den Reparaturmodus (Linux 3.5, glibc 2.18)
- TCP_QUICKACK
-
Quickack-Modus aktivieren (Linux 2.4.4, glibc 2.3)
- TCP_REPAIR
-
Reparaturmodus (Linux 3.5, glibc 2.18)
- TCP_REPAIR_OPTIONS
-
Optionen für den Reparaturmodus (Linux 3.5, glibc 2.18)
- TCP_REPAIR_QUEUE
-
Warteschlange für den Reparaturmodus (Linux 3.5, glibc 2.18)
- TCP_SYNCNT
-
Anzahl der SYN-Neuübertragungen, bevor eine Verbindung getrennt wird (Linux 2.4, glibc 2.2)
- TCP_THIN_DUPACK
-
Behandlung von Duplikatbestätigungen für Thin-Streams (Linux 2.6.34, glibc 2.18)
- TCP_THIN_LINEAR_TIMEOUTS
-
Lineare Timeouts für Thin-Streams (Linux 2.6.34, glibc 2.18)
- TCP_TIMESTAMP
-
TCP-Zeitstempel (Linux 3.9, glibc 2.18)
- TCP_USER_TIMEOUT
-
Maximales Timeout, bevor eine TCP-Verbindung abgebrochen wird (Linux 2.6.37, glibc 2.18)
- TCP_WINDOW_CLAMP
-
Die Größe des angekündigten Fensters begrenzen (Linux 2.4, glibc 2.2)
- UDP_CORK
-
Keine teilweise Frames senden (Linux 2.5.44, glibc 2.11)
Öffentliche Klassenmethoden
Source
# File ext/socket/lib/socket.rb, line 1258 def self.accept_loop(*sockets) # :yield: socket, client_addrinfo sockets.flatten!(1) if sockets.empty? raise ArgumentError, "no sockets" end loop { readable, _, _ = IO.select(sockets) readable.each {|r| sock, addr = r.accept_nonblock(exception: false) next if sock == :wait_readable yield sock, addr } } end
yield Socket und Client-Adresse für jede Verbindung, die über die gegebenen Sockets angenommen wird.
Die Argumente sind eine Liste von Sockets. Das einzelne Argument sollte ein Socket oder ein Array von Sockets sein.
Diese Methode ruft den Block sequenziell auf. Das bedeutet, dass die nächste Verbindung nicht angenommen wird, bis der Block zurückkehrt. Daher solltenConcurrent-Mechanismen, wie Threads, verwendet werden, um mehrere Clients gleichzeitig zu bedienen.
Source
static VALUE
sock_s_getaddrinfo(int argc, VALUE *argv, VALUE _)
{
VALUE host, port, family, socktype, protocol, flags, ret, revlookup;
struct addrinfo hints;
struct rb_addrinfo *res;
int norevlookup;
rb_scan_args(argc, argv, "25", &host, &port, &family, &socktype, &protocol, &flags, &revlookup);
MEMZERO(&hints, struct addrinfo, 1);
hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family);
if (!NIL_P(socktype)) {
hints.ai_socktype = rsock_socktype_arg(socktype);
}
if (!NIL_P(protocol)) {
hints.ai_protocol = NUM2INT(protocol);
}
if (!NIL_P(flags)) {
hints.ai_flags = NUM2INT(flags);
}
if (NIL_P(revlookup) || !rsock_revlookup_flag(revlookup, &norevlookup)) {
norevlookup = rsock_do_not_reverse_lookup;
}
res = rsock_getaddrinfo(host, port, &hints, 0, Qnil);
ret = make_addrinfo(res, norevlookup);
rb_freeaddrinfo(res);
return ret;
}
Ruft Adressinformationen für nodename:servname ab.
Beachten Sie, dass Addrinfo.getaddrinfo die gleiche Funktionalität in einem objektorientierten Stil bietet.
family sollte eine Adressfamilie sein, wie z. B.: :INET, :INET6, usw.
socktype sollte ein Socket-Typ sein, wie z. B.: :STREAM, :DGRAM, :RAW, usw.
protocol sollte ein in der Familie definiertes Protokoll sein und standardmäßig 0 für die Familie sein.
flags sollte eine bitweise OR-Verknüpfung von Socket::AI_* Konstanten sein.
Socket.getaddrinfo("www.ruby-lang.org", "http", nil, :STREAM) #=> [["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68", 2, 1, 6]] # PF_INET/SOCK_STREAM/IPPROTO_TCP Socket.getaddrinfo("localhost", nil) #=> [["AF_INET", 0, "localhost", "127.0.0.1", 2, 1, 6], # PF_INET/SOCK_STREAM/IPPROTO_TCP # ["AF_INET", 0, "localhost", "127.0.0.1", 2, 2, 17], # PF_INET/SOCK_DGRAM/IPPROTO_UDP # ["AF_INET", 0, "localhost", "127.0.0.1", 2, 3, 0]] # PF_INET/SOCK_RAW/IPPROTO_IP
reverse_lookup bestimmt die Form des dritten Elements und muss einer der folgenden Werte sein. Wenn reverse_lookup weggelassen wird, ist der Standardwert nil.
+true+, +:hostname+: hostname is obtained from numeric address using reverse lookup, which may take a time. +false+, +:numeric+: hostname is the same as numeric address. +nil+: obey to the current +do_not_reverse_lookup+ flag.
Wenn ein Addrinfo-Objekt bevorzugt wird, verwenden Sie Addrinfo.getaddrinfo.
Source
static VALUE
sock_s_gethostbyaddr(int argc, VALUE *argv, VALUE _)
{
VALUE addr, family;
struct hostent *h;
char **pch;
VALUE ary, names;
int t = AF_INET;
rb_warn("Socket.gethostbyaddr is deprecated; use Addrinfo#getnameinfo instead.");
rb_scan_args(argc, argv, "11", &addr, &family);
StringValue(addr);
if (!NIL_P(family)) {
t = rsock_family_arg(family);
}
#ifdef AF_INET6
else if (RSTRING_LEN(addr) == 16) {
t = AF_INET6;
}
#endif
h = gethostbyaddr(RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), t);
if (h == NULL) {
#ifdef HAVE_HSTRERROR
extern int h_errno;
rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno));
#else
rb_raise(rb_eSocket, "host not found");
#endif
}
ary = rb_ary_new();
rb_ary_push(ary, rb_str_new2(h->h_name));
names = rb_ary_new();
rb_ary_push(ary, names);
if (h->h_aliases != NULL) {
for (pch = h->h_aliases; *pch; pch++) {
rb_ary_push(names, rb_str_new2(*pch));
}
}
rb_ary_push(ary, INT2NUM(h->h_addrtype));
#ifdef h_addr
for (pch = h->h_addr_list; *pch; pch++) {
rb_ary_push(ary, rb_str_new(*pch, h->h_length));
}
#else
rb_ary_push(ary, rb_str_new(h->h_addr, h->h_length));
#endif
return ary;
}
Verwenden Sie stattdessen Addrinfo#getnameinfo. Diese Methode ist aus folgenden Gründen veraltet
-
Ungewöhnliche Adressdarstellung: 4/16-Byte-Binärzeichenkette zur Darstellung einer IPv4/IPv6-Adresse.
-
gethostbyaddr() kann lange dauern und andere Threads blockieren. (GVL kann nicht freigegeben werden, da gethostbyname() nicht threadsicher ist.)
-
Diese Methode verwendet die Funktion gethostbyname(), die bereits aus POSIX entfernt wurde.
Diese Methode ruft die Host-Informationen für address ab.
p Socket.gethostbyaddr([221,186,184,68].pack("CCCC"))
#=> ["carbon.ruby-lang.org", [], 2, "\xDD\xBA\xB8D"]
p Socket.gethostbyaddr([127,0,0,1].pack("CCCC"))
["localhost", [], 2, "\x7F\x00\x00\x01"]
p Socket.gethostbyaddr(([0]*15+[1]).pack("C"*16))
#=> ["localhost", ["ip6-localhost", "ip6-loopback"], 10,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"]
Source
static VALUE
sock_s_gethostbyname(VALUE obj, VALUE host)
{
rb_warn("Socket.gethostbyname is deprecated; use Addrinfo.getaddrinfo instead.");
struct rb_addrinfo *res =
rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME, Qnil);
return rsock_make_hostent(host, res, sock_sockaddr);
}
Verwenden Sie stattdessen Addrinfo.getaddrinfo. Diese Methode ist aus folgenden Gründen veraltet
-
Das dritte Element des Ergebnisses ist die Adressfamilie der ersten Adresse. Die Adressfamilien der restlichen Adressen werden nicht zurückgegeben.
-
Ungewöhnliche Adressdarstellung: 4/16-Byte-Binärzeichenkette zur Darstellung einer IPv4/IPv6-Adresse.
-
gethostbyname() kann lange dauern und andere Threads blockieren. (GVL kann nicht freigegeben werden, da gethostbyname() nicht threadsicher ist.)
-
Diese Methode verwendet die Funktion gethostbyname(), die bereits aus POSIX entfernt wurde.
Diese Methode ruft die Host-Informationen für hostname ab.
p Socket.gethostbyname("hal") #=> ["localhost", ["hal"], 2, "\x7F\x00\x00\x01"]
Source
static VALUE
sock_gethostname(VALUE obj)
{
#if defined(NI_MAXHOST)
# define RUBY_MAX_HOST_NAME_LEN NI_MAXHOST
#elif defined(HOST_NAME_MAX)
# define RUBY_MAX_HOST_NAME_LEN HOST_NAME_MAX
#else
# define RUBY_MAX_HOST_NAME_LEN 1024
#endif
long len = RUBY_MAX_HOST_NAME_LEN;
VALUE name;
name = rb_str_new(0, len);
while (gethostname(RSTRING_PTR(name), len) < 0) {
int e = errno;
switch (e) {
case ENAMETOOLONG:
#ifdef __linux__
case EINVAL:
/* glibc before version 2.1 uses EINVAL instead of ENAMETOOLONG */
#endif
break;
default:
rb_syserr_fail(e, "gethostname(3)");
}
rb_str_modify_expand(name, len);
len += len;
}
rb_str_resize(name, strlen(RSTRING_PTR(name)));
return name;
}
Gibt den Hostnamen zurück.
p Socket.gethostname #=> "hal"
Beachten Sie, dass die Konvertierung in eine IP-Adresse mit gethostbyname, getaddrinfo usw. nicht garantiert werden kann. Wenn Sie eine lokale IP-Adresse benötigen, verwenden Sie Socket.ip_address_list.
Source
static VALUE
socket_s_getifaddrs(VALUE self)
{
return rsock_getifaddrs();
}
Gibt ein Array von Schnittstellenadressen zurück. Ein Element des Arrays ist eine Instanz von Socket::Ifaddr.
Diese Methode kann verwendet werden, um Multicast-fähige Schnittstellen zu finden
pp Socket.getifaddrs.reject {|ifaddr| !ifaddr.addr.ip? || (ifaddr.flags & Socket::IFF_MULTICAST == 0) }.map {|ifaddr| [ifaddr.name, ifaddr.ifindex, ifaddr.addr] } #=> [["eth0", 2, #<Addrinfo: 221.186.184.67>], # ["eth0", 2, #<Addrinfo: fe80::216:3eff:fe95:88bb%eth0>]]
Beispielergebnis unter GNU/Linux
pp Socket.getifaddrs #=> [#<Socket::Ifaddr lo UP,LOOPBACK,RUNNING,0x10000 PACKET[protocol=0 lo hatype=772 HOST hwaddr=00:00:00:00:00:00]>, # #<Socket::Ifaddr eth0 UP,BROADCAST,RUNNING,MULTICAST,0x10000 PACKET[protocol=0 eth0 hatype=1 HOST hwaddr=00:16:3e:95:88:bb] broadcast=PACKET[protocol=0 eth0 hatype=1 HOST hwaddr=ff:ff:ff:ff:ff:ff]>, # #<Socket::Ifaddr sit0 NOARP PACKET[protocol=0 sit0 hatype=776 HOST hwaddr=00:00:00:00]>, # #<Socket::Ifaddr lo UP,LOOPBACK,RUNNING,0x10000 127.0.0.1 netmask=255.0.0.0>, # #<Socket::Ifaddr eth0 UP,BROADCAST,RUNNING,MULTICAST,0x10000 221.186.184.67 netmask=255.255.255.240 broadcast=221.186.184.79>, # #<Socket::Ifaddr lo UP,LOOPBACK,RUNNING,0x10000 ::1 netmask=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>, # #<Socket::Ifaddr eth0 UP,BROADCAST,RUNNING,MULTICAST,0x10000 fe80::216:3eff:fe95:88bb%eth0 netmask=ffff:ffff:ffff:ffff::>]
Beispielergebnis unter FreeBSD
pp Socket.getifaddrs #=> [#<Socket::Ifaddr usbus0 UP,0x10000 LINK[usbus0]>, # #<Socket::Ifaddr re0 UP,BROADCAST,RUNNING,MULTICAST,0x800 LINK[re0 3a:d0:40:9a:fe:e8]>, # #<Socket::Ifaddr re0 UP,BROADCAST,RUNNING,MULTICAST,0x800 10.250.10.18 netmask=255.255.255.? (7 bytes for 16 bytes sockaddr_in) broadcast=10.250.10.255>, # #<Socket::Ifaddr re0 UP,BROADCAST,RUNNING,MULTICAST,0x800 fe80:2::38d0:40ff:fe9a:fee8 netmask=ffff:ffff:ffff:ffff::>, # #<Socket::Ifaddr re0 UP,BROADCAST,RUNNING,MULTICAST,0x800 2001:2e8:408:10::12 netmask=UNSPEC>, # #<Socket::Ifaddr plip0 POINTOPOINT,MULTICAST,0x800 LINK[plip0]>, # #<Socket::Ifaddr lo0 UP,LOOPBACK,RUNNING,MULTICAST LINK[lo0]>, # #<Socket::Ifaddr lo0 UP,LOOPBACK,RUNNING,MULTICAST ::1 netmask=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>, # #<Socket::Ifaddr lo0 UP,LOOPBACK,RUNNING,MULTICAST fe80:4::1 netmask=ffff:ffff:ffff:ffff::>, # #<Socket::Ifaddr lo0 UP,LOOPBACK,RUNNING,MULTICAST 127.0.0.1 netmask=255.?.?.? (5 bytes for 16 bytes sockaddr_in)>]
Source
static VALUE
sock_s_getnameinfo(int argc, VALUE *argv, VALUE _)
{
VALUE sa, af = Qnil, host = Qnil, port = Qnil, flags, tmp;
char hbuf[1024], pbuf[1024];
int fl;
struct rb_addrinfo *res = NULL;
struct addrinfo hints, *r;
int error, saved_errno;
union_sockaddr ss;
struct sockaddr *sap;
socklen_t salen;
sa = flags = Qnil;
rb_scan_args(argc, argv, "11", &sa, &flags);
fl = 0;
if (!NIL_P(flags)) {
fl = NUM2INT(flags);
}
tmp = rb_check_sockaddr_string_type(sa);
if (!NIL_P(tmp)) {
sa = tmp;
if (sizeof(ss) < (size_t)RSTRING_LEN(sa)) {
rb_raise(rb_eTypeError, "sockaddr length too big");
}
memcpy(&ss, RSTRING_PTR(sa), RSTRING_LEN(sa));
if (!VALIDATE_SOCKLEN(&ss.addr, RSTRING_LEN(sa))) {
rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
}
sap = &ss.addr;
salen = RSTRING_SOCKLEN(sa);
goto call_nameinfo;
}
tmp = rb_check_array_type(sa);
if (!NIL_P(tmp)) {
sa = tmp;
MEMZERO(&hints, struct addrinfo, 1);
if (RARRAY_LEN(sa) == 3) {
af = RARRAY_AREF(sa, 0);
port = RARRAY_AREF(sa, 1);
host = RARRAY_AREF(sa, 2);
}
else if (RARRAY_LEN(sa) >= 4) {
af = RARRAY_AREF(sa, 0);
port = RARRAY_AREF(sa, 1);
host = RARRAY_AREF(sa, 3);
if (NIL_P(host)) {
host = RARRAY_AREF(sa, 2);
}
else {
/*
* 4th element holds numeric form, don't resolve.
* see rsock_ipaddr().
*/
#ifdef AI_NUMERICHOST /* AIX 4.3.3 doesn't have AI_NUMERICHOST. */
hints.ai_flags |= AI_NUMERICHOST;
#endif
}
}
else {
rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given",
RARRAY_LEN(sa));
}
hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
/* af */
hints.ai_family = NIL_P(af) ? PF_UNSPEC : rsock_family_arg(af);
res = rsock_getaddrinfo(host, port, &hints, 0, Qnil);
sap = res->ai->ai_addr;
salen = res->ai->ai_addrlen;
}
else {
rb_raise(rb_eTypeError, "expecting String or Array");
}
call_nameinfo:
error = rb_getnameinfo(sap, salen, hbuf, sizeof(hbuf),
pbuf, sizeof(pbuf), fl);
if (error) goto error_exit_name;
if (res) {
for (r = res->ai->ai_next; r; r = r->ai_next) {
char hbuf2[1024], pbuf2[1024];
sap = r->ai_addr;
salen = r->ai_addrlen;
error = rb_getnameinfo(sap, salen, hbuf2, sizeof(hbuf2),
pbuf2, sizeof(pbuf2), fl);
if (error) goto error_exit_name;
if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) {
rb_freeaddrinfo(res);
rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename");
}
}
rb_freeaddrinfo(res);
}
return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
error_exit_name:
saved_errno = errno;
if (res) rb_freeaddrinfo(res);
errno = saved_errno;
rsock_raise_resolution_error("getnameinfo", error);
UNREACHABLE_RETURN(Qnil);
}
Ruft Namensinformationen für sockaddr ab.
sockaddr sollte einer der folgenden sein.
-
gepackte sockaddr-Zeichenkette wie
Socket.sockaddr_in(80, "127.0.0.1") -
3-Element-Array wie ["AF_INET", 80, "127.0.0.1"]
-
4-Element-Array wie ["AF_INET", 80, ignoriert, "127.0.0.1"]
flags sollte eine bitweise OR-Verknüpfung von Socket::NI_* Konstanten sein.
Hinweis: Die letzte Form ist kompatibel mit IPSocket#addr und IPSocket#peeraddr.
Socket.getnameinfo(Socket.sockaddr_in(80, "127.0.0.1")) #=> ["localhost", "www"] Socket.getnameinfo(["AF_INET", 80, "127.0.0.1"]) #=> ["localhost", "www"] Socket.getnameinfo(["AF_INET", 80, "localhost", "127.0.0.1"]) #=> ["localhost", "www"]
Wenn ein Addrinfo-Objekt bevorzugt wird, verwenden Sie Addrinfo#getnameinfo.
Source
static VALUE
sock_s_getservbyname(int argc, VALUE *argv, VALUE _)
{
VALUE service, proto;
struct servent *sp;
long port;
const char *servicename, *protoname = "tcp";
rb_scan_args(argc, argv, "11", &service, &proto);
StringValue(service);
if (!NIL_P(proto)) StringValue(proto);
servicename = StringValueCStr(service);
if (!NIL_P(proto)) protoname = StringValueCStr(proto);
sp = getservbyname(servicename, protoname);
if (sp) {
port = ntohs(sp->s_port);
}
else {
char *end;
port = STRTOUL(servicename, &end, 0);
if (*end != '\0') {
rb_raise(rb_eSocket, "no such service %s/%s", servicename, protoname);
}
}
return INT2FIX(port);
}
Ruft die Portnummer für service_name ab.
Wenn protocol_name nicht angegeben wird, wird "tcp" angenommen.
Socket.getservbyname("smtp") #=> 25 Socket.getservbyname("shell") #=> 514 Socket.getservbyname("syslog", "udp") #=> 514
Source
static VALUE
sock_s_getservbyport(int argc, VALUE *argv, VALUE _)
{
VALUE port, proto;
struct servent *sp;
long portnum;
const char *protoname = "tcp";
rb_scan_args(argc, argv, "11", &port, &proto);
portnum = NUM2LONG(port);
if (portnum != (uint16_t)portnum) {
const char *s = portnum > 0 ? "big" : "small";
rb_raise(rb_eRangeError, "integer %ld too %s to convert into `int16_t'", portnum, s);
}
if (!NIL_P(proto)) protoname = StringValueCStr(proto);
sp = getservbyport((int)htons((uint16_t)portnum), protoname);
if (!sp) {
rb_raise(rb_eSocket, "no such service for port %d/%s", (int)portnum, protoname);
}
return rb_str_new2(sp->s_name);
}
Ruft die Portnummer für port ab.
Wenn protocol_name nicht angegeben wird, wird "tcp" angenommen.
Socket.getservbyport(80) #=> "www" Socket.getservbyport(514, "tcp") #=> "shell" Socket.getservbyport(514, "udp") #=> "syslog"
Source
static VALUE
socket_s_ip_address_list(VALUE self)
{
#if defined(HAVE_GETIFADDRS)
struct ifaddrs *ifp = NULL;
struct ifaddrs *p;
int ret;
VALUE list;
ret = getifaddrs(&ifp);
if (ret == -1) {
rb_sys_fail("getifaddrs");
}
list = rb_ary_new();
for (p = ifp; p; p = p->ifa_next) {
if (p->ifa_addr != NULL && IS_IP_FAMILY(p->ifa_addr->sa_family)) {
struct sockaddr *addr = p->ifa_addr;
#if defined(AF_INET6) && defined(__sun)
/*
* OpenIndiana SunOS 5.11 getifaddrs() returns IPv6 link local
* address with sin6_scope_id == 0.
* So fill it from the interface name (ifa_name).
*/
struct sockaddr_in6 addr6;
if (addr->sa_family == AF_INET6) {
socklen_t len = (socklen_t)sizeof(struct sockaddr_in6);
memcpy(&addr6, addr, len);
addr = (struct sockaddr *)&addr6;
if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) &&
addr6.sin6_scope_id == 0) {
unsigned int ifindex = if_nametoindex(p->ifa_name);
if (ifindex != 0) {
addr6.sin6_scope_id = ifindex;
}
}
}
#endif
rb_ary_push(list, sockaddr_obj(addr, sockaddr_len(addr)));
}
}
freeifaddrs(ifp);
return list;
#elif defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM)
/* Solaris if_tcp(7P) */
int fd = -1;
int ret;
struct lifnum ln;
struct lifconf lc;
const char *reason = NULL;
int save_errno;
int i;
VALUE list = Qnil;
lc.lifc_buf = NULL;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1)
rb_sys_fail("socket(2)");
memset(&ln, 0, sizeof(ln));
ln.lifn_family = AF_UNSPEC;
ret = ioctl(fd, SIOCGLIFNUM, &ln);
if (ret == -1) {
reason = "SIOCGLIFNUM";
goto finish;
}
memset(&lc, 0, sizeof(lc));
lc.lifc_family = AF_UNSPEC;
lc.lifc_flags = 0;
lc.lifc_len = sizeof(struct lifreq) * ln.lifn_count;
lc.lifc_req = xmalloc(lc.lifc_len);
ret = ioctl(fd, SIOCGLIFCONF, &lc);
if (ret == -1) {
reason = "SIOCGLIFCONF";
goto finish;
}
list = rb_ary_new();
for (i = 0; i < ln.lifn_count; i++) {
struct lifreq *req = &lc.lifc_req[i];
if (IS_IP_FAMILY(req->lifr_addr.ss_family)) {
if (req->lifr_addr.ss_family == AF_INET6 &&
IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_addr) &&
((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id == 0) {
struct lifreq req2;
memcpy(req2.lifr_name, req->lifr_name, LIFNAMSIZ);
ret = ioctl(fd, SIOCGLIFINDEX, &req2);
if (ret == -1) {
reason = "SIOCGLIFINDEX";
goto finish;
}
((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id = req2.lifr_index;
}
rb_ary_push(list, sockaddr_obj((struct sockaddr *)&req->lifr_addr, req->lifr_addrlen));
}
}
finish:
save_errno = errno;
xfree(lc.lifc_req);
if (fd != -1)
close(fd);
errno = save_errno;
if (reason)
rb_syserr_fail(save_errno, reason);
return list;
#elif defined(SIOCGIFCONF)
int fd = -1;
int ret;
#define EXTRA_SPACE ((int)(sizeof(struct ifconf) + sizeof(union_sockaddr)))
char initbuf[4096+EXTRA_SPACE];
char *buf = initbuf;
int bufsize;
struct ifconf conf;
struct ifreq *req;
VALUE list = Qnil;
const char *reason = NULL;
int save_errno;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1)
rb_sys_fail("socket(2)");
bufsize = sizeof(initbuf);
buf = initbuf;
retry:
conf.ifc_len = bufsize;
conf.ifc_req = (struct ifreq *)buf;
/* fprintf(stderr, "bufsize: %d\n", bufsize); */
ret = ioctl(fd, SIOCGIFCONF, &conf);
if (ret == -1) {
reason = "SIOCGIFCONF";
goto finish;
}
/* fprintf(stderr, "conf.ifc_len: %d\n", conf.ifc_len); */
if (bufsize - EXTRA_SPACE < conf.ifc_len) {
if (bufsize < conf.ifc_len) {
/* NetBSD returns required size for all interfaces. */
bufsize = conf.ifc_len + EXTRA_SPACE;
}
else {
bufsize = bufsize << 1;
}
if (buf == initbuf)
buf = NULL;
buf = xrealloc(buf, bufsize);
goto retry;
}
close(fd);
fd = -1;
list = rb_ary_new();
req = conf.ifc_req;
while ((char*)req < (char*)conf.ifc_req + conf.ifc_len) {
struct sockaddr *addr = &req->ifr_addr;
if (IS_IP_FAMILY(addr->sa_family)) {
rb_ary_push(list, sockaddr_obj(addr, sockaddr_len(addr)));
}
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
# ifndef _SIZEOF_ADDR_IFREQ
# define _SIZEOF_ADDR_IFREQ(r) \
(sizeof(struct ifreq) + \
(sizeof(struct sockaddr) < (r).ifr_addr.sa_len ? \
(r).ifr_addr.sa_len - sizeof(struct sockaddr) : \
0))
# endif
req = (struct ifreq *)((char*)req + _SIZEOF_ADDR_IFREQ(*req));
#else
req = (struct ifreq *)((char*)req + sizeof(struct ifreq));
#endif
}
finish:
save_errno = errno;
if (buf != initbuf)
xfree(buf);
if (fd != -1)
close(fd);
errno = save_errno;
if (reason)
rb_syserr_fail(save_errno, reason);
return list;
#undef EXTRA_SPACE
#elif defined(_WIN32)
typedef struct ip_adapter_unicast_address_st {
unsigned LONG_LONG dummy0;
struct ip_adapter_unicast_address_st *Next;
struct {
struct sockaddr *lpSockaddr;
int iSockaddrLength;
} Address;
int dummy1;
int dummy2;
int dummy3;
long dummy4;
long dummy5;
long dummy6;
} ip_adapter_unicast_address_t;
typedef struct ip_adapter_anycast_address_st {
unsigned LONG_LONG dummy0;
struct ip_adapter_anycast_address_st *Next;
struct {
struct sockaddr *lpSockaddr;
int iSockaddrLength;
} Address;
} ip_adapter_anycast_address_t;
typedef struct ip_adapter_addresses_st {
unsigned LONG_LONG dummy0;
struct ip_adapter_addresses_st *Next;
void *dummy1;
ip_adapter_unicast_address_t *FirstUnicastAddress;
ip_adapter_anycast_address_t *FirstAnycastAddress;
void *dummy2;
void *dummy3;
void *dummy4;
void *dummy5;
void *dummy6;
BYTE dummy7[8];
DWORD dummy8;
DWORD dummy9;
DWORD dummy10;
DWORD IfType;
int OperStatus;
DWORD dummy12;
DWORD dummy13[16];
void *dummy14;
} ip_adapter_addresses_t;
typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG, ULONG, PVOID, ip_adapter_addresses_t *, PULONG);
HMODULE h;
GetAdaptersAddresses_t pGetAdaptersAddresses;
ULONG len;
DWORD ret;
ip_adapter_addresses_t *adapters;
VALUE list;
h = LoadLibrary("iphlpapi.dll");
if (!h)
rb_notimplement();
pGetAdaptersAddresses = (GetAdaptersAddresses_t)GetProcAddress(h, "GetAdaptersAddresses");
if (!pGetAdaptersAddresses) {
FreeLibrary(h);
rb_notimplement();
}
ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &len);
if (ret != ERROR_SUCCESS && ret != ERROR_BUFFER_OVERFLOW) {
errno = rb_w32_map_errno(ret);
FreeLibrary(h);
rb_sys_fail("GetAdaptersAddresses");
}
adapters = (ip_adapter_addresses_t *)ALLOCA_N(BYTE, len);
ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
if (ret != ERROR_SUCCESS) {
errno = rb_w32_map_errno(ret);
FreeLibrary(h);
rb_sys_fail("GetAdaptersAddresses");
}
list = rb_ary_new();
for (; adapters; adapters = adapters->Next) {
ip_adapter_unicast_address_t *uni;
ip_adapter_anycast_address_t *any;
if (adapters->OperStatus != 1) /* 1 means IfOperStatusUp */
continue;
for (uni = adapters->FirstUnicastAddress; uni; uni = uni->Next) {
#ifndef INET6
if (uni->Address.lpSockaddr->sa_family == AF_INET)
#else
if (IS_IP_FAMILY(uni->Address.lpSockaddr->sa_family))
#endif
rb_ary_push(list, sockaddr_obj(uni->Address.lpSockaddr, uni->Address.iSockaddrLength));
}
for (any = adapters->FirstAnycastAddress; any; any = any->Next) {
#ifndef INET6
if (any->Address.lpSockaddr->sa_family == AF_INET)
#else
if (IS_IP_FAMILY(any->Address.lpSockaddr->sa_family))
#endif
rb_ary_push(list, sockaddr_obj(any->Address.lpSockaddr, any->Address.iSockaddrLength));
}
}
FreeLibrary(h);
return list;
#endif
}
Gibt lokale IP-Adressen als Array zurück.
Das Array enthält Addrinfo-Objekte.
pp Socket.ip_address_list
#=> [#<Addrinfo: 127.0.0.1>,
#<Addrinfo: 192.168.0.128>,
#<Addrinfo: ::1>,
...]
Source
static VALUE
sock_initialize(int argc, VALUE *argv, VALUE sock)
{
VALUE domain, type, protocol;
int fd;
int d, t;
rb_scan_args(argc, argv, "21", &domain, &type, &protocol);
if (NIL_P(protocol))
protocol = INT2FIX(0);
setup_domain_and_type(domain, &d, type, &t);
fd = rsock_socket(d, t, NUM2INT(protocol));
if (fd < 0) rb_sys_fail("socket(2)");
return rsock_init_sock(sock, fd);
}
Erstellt ein neues Socket-Objekt.
domain sollte eine Kommunikationsdomäne sein, wie z. B.: :INET, :INET6, :UNIX, usw.
socktype sollte ein Socket-Typ sein, wie z. B.: :STREAM, :DGRAM, :RAW, usw.
protocol ist optional und sollte ein in der Domäne definiertes Protokoll sein. Wenn kein Protokoll angegeben wird, wird intern 0 verwendet.
Socket.new(:INET, :STREAM) # TCP socket Socket.new(:INET, :DGRAM) # UDP socket Socket.new(:UNIX, :STREAM) # UNIX stream socket Socket.new(:UNIX, :DGRAM) # UNIX datagram socket
Source
static VALUE
sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host)
{
struct rb_addrinfo *res = rsock_addrinfo(host, port, AF_UNSPEC, 0, 0, Qnil);
VALUE addr = rb_str_new((char*)res->ai->ai_addr, res->ai->ai_addrlen);
rb_freeaddrinfo(res);
return addr;
}
Packt port und host als AF_INET/AF_INET6 sockaddr-Zeichenkette.
Socket.sockaddr_in(80, "127.0.0.1") #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" Socket.sockaddr_in(80, "::1") #=> "\n\x00\x00P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00"
Source
static VALUE
sock_s_pack_sockaddr_un(VALUE self, VALUE path)
{
struct sockaddr_un sockaddr;
VALUE addr;
StringValue(path);
INIT_SOCKADDR_UN(&sockaddr, sizeof(struct sockaddr_un));
if (sizeof(sockaddr.sun_path) < (size_t)RSTRING_LEN(path)) {
rb_raise(rb_eArgError, "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
(size_t)RSTRING_LEN(path), sizeof(sockaddr.sun_path));
}
memcpy(sockaddr.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
addr = rb_str_new((char*)&sockaddr, rsock_unix_sockaddr_len(path));
return addr;
}
Packt path als AF_UNIX sockaddr-Zeichenkette (AF_UNIX).
Socket.sockaddr_un("/tmp/sock") #=> "\x01\x00/tmp/sock\x00\x00..."
Source
VALUE
rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass)
{
VALUE domain, type, protocol;
int d, t, p, sp[2];
int ret;
VALUE s1, s2, r;
rb_scan_args(argc, argv, "21", &domain, &type, &protocol);
if (NIL_P(protocol))
protocol = INT2FIX(0);
setup_domain_and_type(domain, &d, type, &t);
p = NUM2INT(protocol);
ret = rsock_socketpair(d, t, p, sp);
if (ret < 0) {
rb_sys_fail("socketpair(2)");
}
s1 = rsock_init_sock(rb_obj_alloc(klass), sp[0]);
s2 = rsock_init_sock(rb_obj_alloc(klass), sp[1]);
r = rb_assoc_new(s1, s2);
if (rb_block_given_p()) {
return rb_ensure(pair_yield, r, io_close, s1);
}
return r;
}
Erstellt ein Paar von miteinander verbundenen Sockets.
domain sollte eine Kommunikationsdomäne sein, wie z. B.: :INET, :INET6, :UNIX, usw.
socktype sollte ein Socket-Typ sein, wie z. B.: :STREAM, :DGRAM, :RAW, usw.
protocol sollte ein in der Domäne definiertes Protokoll sein und standardmäßig 0 für die Domäne sein.
s1, s2 = Socket.pair(:UNIX, :STREAM, 0) s1.send "a", 0 s1.send "b", 0 s1.close p s2.recv(10) #=> "ab" p s2.recv(10) #=> "" p s2.recv(10) #=> "" s1, s2 = Socket.pair(:UNIX, :DGRAM, 0) s1.send "a", 0 s1.send "b", 0 p s2.recv(10) #=> "a" p s2.recv(10) #=> "b"
Source
static VALUE
sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host)
{
struct rb_addrinfo *res = rsock_addrinfo(host, port, AF_UNSPEC, 0, 0, Qnil);
VALUE addr = rb_str_new((char*)res->ai->ai_addr, res->ai->ai_addrlen);
rb_freeaddrinfo(res);
return addr;
}
Packt port und host als AF_INET/AF_INET6 sockaddr-Zeichenkette.
Socket.sockaddr_in(80, "127.0.0.1") #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" Socket.sockaddr_in(80, "::1") #=> "\n\x00\x00P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00"
Source
static VALUE
sock_s_pack_sockaddr_un(VALUE self, VALUE path)
{
struct sockaddr_un sockaddr;
VALUE addr;
StringValue(path);
INIT_SOCKADDR_UN(&sockaddr, sizeof(struct sockaddr_un));
if (sizeof(sockaddr.sun_path) < (size_t)RSTRING_LEN(path)) {
rb_raise(rb_eArgError, "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
(size_t)RSTRING_LEN(path), sizeof(sockaddr.sun_path));
}
memcpy(sockaddr.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
addr = rb_str_new((char*)&sockaddr, rsock_unix_sockaddr_len(path));
return addr;
}
Packt path als AF_UNIX sockaddr-Zeichenkette (AF_UNIX).
Socket.sockaddr_un("/tmp/sock") #=> "\x01\x00/tmp/sock\x00\x00..."
Source
VALUE
rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass)
{
VALUE domain, type, protocol;
int d, t, p, sp[2];
int ret;
VALUE s1, s2, r;
rb_scan_args(argc, argv, "21", &domain, &type, &protocol);
if (NIL_P(protocol))
protocol = INT2FIX(0);
setup_domain_and_type(domain, &d, type, &t);
p = NUM2INT(protocol);
ret = rsock_socketpair(d, t, p, sp);
if (ret < 0) {
rb_sys_fail("socketpair(2)");
}
s1 = rsock_init_sock(rb_obj_alloc(klass), sp[0]);
s2 = rsock_init_sock(rb_obj_alloc(klass), sp[1]);
r = rb_assoc_new(s1, s2);
if (rb_block_given_p()) {
return rb_ensure(pair_yield, r, io_close, s1);
}
return r;
}
Erstellt ein Paar von miteinander verbundenen Sockets.
domain sollte eine Kommunikationsdomäne sein, wie z. B.: :INET, :INET6, :UNIX, usw.
socktype sollte ein Socket-Typ sein, wie z. B.: :STREAM, :DGRAM, :RAW, usw.
protocol sollte ein in der Domäne definiertes Protokoll sein und standardmäßig 0 für die Domäne sein.
s1, s2 = Socket.pair(:UNIX, :STREAM, 0) s1.send "a", 0 s1.send "b", 0 s1.close p s2.recv(10) #=> "ab" p s2.recv(10) #=> "" p s2.recv(10) #=> "" s1, s2 = Socket.pair(:UNIX, :DGRAM, 0) s1.send "a", 0 s1.send "b", 0 p s2.recv(10) #=> "a" p s2.recv(10) #=> "b"
Source
# File ext/socket/lib/socket.rb, line 662 def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, open_timeout: nil, fast_fallback: tcp_fast_fallback, &) # :yield: socket if open_timeout && (connect_timeout || resolv_timeout) raise ArgumentError, "Cannot specify open_timeout along with connect_timeout or resolv_timeout" end sock = if fast_fallback && !(host && ip_address?(host)) tcp_with_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, open_timeout:) else tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, open_timeout:) end if block_given? begin yield sock ensure sock.close end else sock end end
Erstellt ein neues Socket-Objekt, das über TCP/IP mit host:port verbunden ist.
Ab Ruby 3.4 arbeitet diese Methode standardmäßig nach dem Happy Eyeballs Version 2 (RFC 8305) Algorithmus.
Weitere Informationen zu Happy Eyeballs Version 2 finden Sie unter Socket.tcp_fast_fallback=.
Damit es sich wie in Ruby 3.3 und früher verhält, geben Sie explizit die Option fast_fallback:false an. Oder, wenn Sie Socket.tcp_fast_fallback=false setzen, wird Happy Eyeballs Version 2 nicht nur für diese Methode, sondern global für alle Socket deaktiviert.
Wenn local_host:local_port angegeben wird, wird der Socket damit gebunden.
Das optionale letzte Argument opts sind Optionen, die durch einen Hash dargestellt werden. opts kann folgende Optionen enthalten
- :resolv_timeout
-
Gibt das Timeout in Sekunden an, ab dem die Namensauflösung beginnt.
- :connect_timeout
-
Diese Methode versucht sequenziell, eine Verbindung zu allen Zieladressen herzustellen.
Dasconnect_timeoutgibt das Timeout in Sekunden ab dem Beginn des Verbindungsversuchs bis zur letzten Kandidatenadresse an.
Standardmäßig werden alle Verbindungsversuche fortgesetzt, bis das Timeout auftritt.
Wennfast_fallback:falseexplizit angegeben wird,
wird ein Timeout für jeden Verbindungsversuch gesetzt und jeder Verbindungsversuch, der sein Timeout überschreitet, wird abgebrochen. - :open_timeout
-
Gibt das Timeout in Sekunden ab dem Beginn der Methodenausführung an.
Wenn dieses Timeout erreicht ist, während noch Adressen vorhanden sind, die noch nicht für die Verbindung versucht wurden, werden keine weiteren Versuche unternommen.
Wenn diese Option zusammen mit anderen Timeout-Optionen angegeben wird, wird eineArgumentErrorausgelöst. - :fast_fallback
-
Aktiviert den Happy Eyeballs Version 2 Algorithmus (standardmäßig aktiviert).
Wenn ein Block angegeben wird, wird der Block mit dem Socket aufgerufen. Der Wert des Blocks wird zurückgegeben. Der Socket wird geschlossen, wenn diese Methode zurückkehrt.
Wenn kein Block angegeben wird, wird der Socket zurückgegeben.
Socket.tcp("www.ruby-lang.org", 80) {|sock| sock.print "GET / HTTP/1.0\r\nHost: www.ruby-lang.org\r\n\r\n" sock.close_write puts sock.read }
Source
VALUE socket_s_tcp_fast_fallback(VALUE self) {
return rb_ivar_get(rb_cSocket, tcp_fast_fallback);
}
Gibt zurück, ob Happy Eyeballs Version 2 (RFC 8305), die ab Ruby 3.4 bei der Verwendung von TCPSocket.new und Socket.tcp bereitgestellt wird, aktiviert oder deaktiviert ist.
Wenn true, ist es für TCPSocket.new und Socket.tcp aktiviert. (Hinweis: Happy Eyeballs Version 2 wird unter Windows nicht bereitgestellt, wenn TCPSocket.new verwendet wird.)
Wenn false, ist Happy Eyeballs Version 2 deaktiviert.
Weitere Informationen zu Happy Eyeballs Version 2 finden Sie unter Socket.tcp_fast_fallback=.
Source
VALUE socket_s_tcp_fast_fallback_set(VALUE self, VALUE value) {
rb_ivar_set(rb_cSocket, tcp_fast_fallback, value);
return value;
}
Aktiviert oder deaktiviert Happy Eyeballs Version 2 (RFC 8305) global, die ab Ruby 3.4 bei der Verwendung von TCPSocket.new und Socket.tcp bereitgestellt wird.
Wenn auf true gesetzt, ist die Funktion sowohl für `TCPSocket.new` als auch für `Socket.tcp` aktiviert. (Hinweis: Diese Funktion ist unter Windows nicht verfügbar, wenn TCPSocket.new verwendet wird.)
Wenn auf false gesetzt, verhält sich das Verhalten wie in Ruby 3.3 oder früher.
Der Standardwert ist true, wenn kein Wert explizit durch Aufrufen dieser Methode gesetzt wird. Wenn jedoch die Umgebungsvariable RUBY_TCP_NO_FAST_FALLBACK=1 gesetzt ist, ist der Standardwert false.
Um die Einstellung pro Methode zu steuern, verwenden Sie das Keyword-Argument fast_fallback für jede Methode.
Happy Eyeballs Version 2
Happy Eyeballs Version 2 (RFC 8305) ist ein Algorithmus zur Verbesserung der Client-Socket-Konnektivität.
Er zielt auf zuverlässigere und effizientere Verbindungen ab, indem er die Namensauflösung und Verbindungsversuche parallel statt seriell durchführt.
Ab Ruby 3.4 arbeitet diese Methode wie folgt mit diesem Algorithmus
-
Beginnen Sie mit der parallelen Auflösung von IPv6- und IPv4-Adressen.
-
Beginnen Sie mit der Verbindung zu einer der zuerst erhaltenen Adressen.
Wenn zuerst IPv4-Adressen erhalten werden, wartet die Methode 50 ms auf die IPv6-Namensauflösung, um IPv6-Verbindungen zu priorisieren. -
Nachdem ein Verbindungsversuch gestartet wurde, warten Sie 250 ms, bis die Verbindung hergestellt ist.
Wenn innerhalb dieser Zeit keine Verbindung hergestellt wird, wird alle 250 ms eine neue Verbindung gestartet
bis eine Verbindung hergestellt ist oder keine Kandidatenadressen mehr vorhanden sind.
(Obwohl RFC 8305 streng die Adresssortierung vorschreibt,
wechselt diese Methode aufgrund von Leistungsproblemen nur zwischen IPv6- und IPv4-Adressen) -
Sobald eine Verbindung hergestellt ist, werden alle verbleibenden Verbindungsversuche abgebrochen.
Source
# File ext/socket/lib/socket.rb, line 1314 def self.tcp_server_loop(host=nil, port, &b) # :yield: socket, client_addrinfo tcp_server_sockets(host, port) {|sockets| accept_loop(sockets, &b) } end
Erstellt einen TCP/IP-Server auf port und ruft den Block für jede angenommene Verbindung auf. Der Block wird mit einem Socket und einer Client-Adresse als Addrinfo-Objekt aufgerufen.
Wenn host angegeben wird, wird er zusammen mit port verwendet, um die Serveradressen zu bestimmen.
Der Socket wird **nicht** geschlossen, wenn der Block zurückkehrt. Die Anwendung sollte ihn also explizit schließen.
Diese Methode ruft den Block sequenziell auf. Das bedeutet, dass die nächste Verbindung nicht angenommen wird, bis der Block zurückkehrt. Daher solltenConcurrent-Mechanismen, wie Threads, verwendet werden, um mehrere Clients gleichzeitig zu bedienen.
Beachten Sie, dass Addrinfo.getaddrinfo verwendet wird, um die Server-Socket-Adressen zu ermitteln. Wenn Addrinfo.getaddrinfo zwei oder mehr Adressen zurückgibt, z. B. IPv4- und IPv6-Adressen, werden alle verwendet. Socket.tcp_server_loop ist erfolgreich, wenn mindestens ein Socket verwendet werden kann.
# Sequential echo server. # It services only one client at a time. Socket.tcp_server_loop(16807) {|sock, client_addrinfo| begin IO.copy_stream(sock, sock) ensure sock.close end } # Threaded echo server # It services multiple clients at a time. # Note that it may accept connections too much. Socket.tcp_server_loop(16807) {|sock, client_addrinfo| Thread.new { begin IO.copy_stream(sock, sock) ensure sock.close end } }
Source
# File ext/socket/lib/socket.rb, line 1214 def self.tcp_server_sockets(host=nil, port) if port == 0 sockets = tcp_server_sockets_port0(host) else last_error = nil sockets = [] begin Addrinfo.foreach(host, port, nil, :STREAM, nil, Socket::AI_PASSIVE) {|ai| begin s = ai.listen rescue SystemCallError last_error = $! next end sockets << s } if sockets.empty? raise last_error end rescue Exception sockets.each(&:close) raise end end if block_given? begin yield sockets ensure sockets.each(&:close) end else sockets end end
Erstellt TCP/IP-Server-Sockets für host und port. host ist optional.
Wenn kein Block angegeben wird, gibt sie ein Array von lauschenden Sockets zurück.
Wenn ein Block angegeben wird, wird der Block mit den Sockets aufgerufen. Der Wert des Blocks wird zurückgegeben. Die Sockets werden geschlossen, wenn diese Methode zurückkehrt.
Wenn port 0 ist, wird der tatsächliche Port dynamisch gewählt. Alle Sockets im Ergebnis haben jedoch denselben Port.
# tcp_server_sockets returns two sockets. sockets = Socket.tcp_server_sockets(1296) p sockets #=> [#<Socket:fd 3>, #<Socket:fd 4>] # The sockets contains IPv6 and IPv4 sockets. sockets.each {|s| p s.local_address } #=> #<Addrinfo: [::]:1296 TCP> # #<Addrinfo: 0.0.0.0:1296 TCP> # IPv6 and IPv4 socket has same port number, 53114, even if it is chosen dynamically. sockets = Socket.tcp_server_sockets(0) sockets.each {|s| p s.local_address } #=> #<Addrinfo: [::]:53114 TCP> # #<Addrinfo: 0.0.0.0:53114 TCP> # The block is called with the sockets. Socket.tcp_server_sockets(0) {|sockets| p sockets #=> [#<Socket:fd 3>, #<Socket:fd 4>] }
Source
# File ext/socket/lib/socket.rb, line 1484 def self.udp_server_loop(host=nil, port, &b) # :yield: message, message_source udp_server_sockets(host, port) {|sockets| udp_server_loop_on(sockets, &b) } end
Erstellt einen UDP/IP-Server auf port und ruft den Block für jede angekommene Nachricht auf. Der Block wird mit der Nachricht und ihrer Quellinformation aufgerufen.
Diese Methode weist intern Sockets unter Verwendung von port zu. Wenn host angegeben wird, wird er in Verbindung mit port zur Bestimmung der Serveradressen verwendet.
Der msg ist eine Zeichenkette.
Der msg_src ist ein Socket::UDPSource-Objekt. Er wird für die Antwort verwendet.
# UDP/IP echo server. Socket.udp_server_loop(9261) {|msg, msg_src| msg_src.reply msg }
Source
# File ext/socket/lib/socket.rb, line 1457 def self.udp_server_loop_on(sockets, &b) # :yield: msg, msg_src loop { readable, _, _ = IO.select(sockets) udp_server_recv(readable, &b) } end
Führt die UDP/IP-Server-Schleife auf den angegebenen Sockets aus.
Der Rückgabewert von Socket.udp_server_sockets ist für das Argument geeignet.
Sie ruft den Block für jede empfangene Nachricht auf.
Source
# File ext/socket/lib/socket.rb, line 1430 def self.udp_server_recv(sockets) sockets.each {|r| msg, sender_addrinfo, _, *controls = r.recvmsg_nonblock(exception: false) next if msg == :wait_readable ai = r.local_address if ai.ipv6? and pktinfo = controls.find {|c| c.cmsg_is?(:IPV6, :PKTINFO) } ai = Addrinfo.udp(pktinfo.ipv6_pktinfo_addr.ip_address, ai.ip_port) yield msg, UDPSource.new(sender_addrinfo, ai) {|reply_msg| r.sendmsg reply_msg, 0, sender_addrinfo, pktinfo } else yield msg, UDPSource.new(sender_addrinfo, ai) {|reply_msg| r.send reply_msg, 0, sender_addrinfo } end } end
Empfängt UDP/IP-Pakete von den angegebenen sockets. Für jedes empfangene Paket wird der Block aufgerufen.
Der Block empfängt msg und msg_src. msg ist eine Zeichenkette mit der Nutzlast des empfangenen Pakets. msg_src ist ein Socket::UDPSource-Objekt, das für die Antwort verwendet wird.
Socket.udp_server_loop kann mit dieser Methode wie folgt implementiert werden.
udp_server_sockets(host, port) {|sockets|
loop {
readable, _, _ = IO.select(sockets)
udp_server_recv(readable) {|msg, msg_src| ... }
}
}
Source
# File ext/socket/lib/socket.rb, line 1342 def self.udp_server_sockets(host=nil, port) last_error = nil sockets = [] ipv6_recvpktinfo = nil if defined? Socket::AncillaryData if defined? Socket::IPV6_RECVPKTINFO # RFC 3542 ipv6_recvpktinfo = Socket::IPV6_RECVPKTINFO elsif defined? Socket::IPV6_PKTINFO # RFC 2292 ipv6_recvpktinfo = Socket::IPV6_PKTINFO end end local_addrs = Socket.ip_address_list ip_list = [] Addrinfo.foreach(host, port, nil, :DGRAM, nil, Socket::AI_PASSIVE) {|ai| if ai.ipv4? && ai.ip_address == "0.0.0.0" local_addrs.each {|a| next unless a.ipv4? ip_list << Addrinfo.new(a.to_sockaddr, :INET, :DGRAM, 0); } elsif ai.ipv6? && ai.ip_address == "::" && !ipv6_recvpktinfo local_addrs.each {|a| next unless a.ipv6? ip_list << Addrinfo.new(a.to_sockaddr, :INET6, :DGRAM, 0); } else ip_list << ai end } ip_list.uniq!(&:to_sockaddr) if port == 0 sockets = ip_sockets_port0(ip_list, false) else ip_list.each {|ip| ai = Addrinfo.udp(ip.ip_address, port) begin s = ai.bind rescue SystemCallError last_error = $! next end sockets << s } if sockets.empty? raise last_error end end sockets.each {|s| ai = s.local_address if ipv6_recvpktinfo && ai.ipv6? && ai.ip_address == "::" s.setsockopt(:IPV6, ipv6_recvpktinfo, 1) end } if block_given? begin yield sockets ensure sockets.each(&:close) if sockets end else sockets end end
Erstellt UDP/IP-Sockets für einen UDP-Server.
Wenn kein Block angegeben wird, gibt sie ein Array von Sockets zurück.
Wenn ein Block angegeben wird, wird der Block mit den Sockets aufgerufen. Der Wert des Blocks wird zurückgegeben. Die Sockets werden geschlossen, wenn diese Methode zurückkehrt.
Wenn port null ist, wird ein Port gewählt. Der gewählte Port wird jedoch für alle Sockets verwendet.
# UDP/IP echo server Socket.udp_server_sockets(0) {|sockets| p sockets.first.local_address.ip_port #=> 32963 Socket.udp_server_loop_on(sockets) {|msg, msg_src| msg_src.reply msg } }
Source
# File ext/socket/lib/socket.rb, line 1534 def self.unix(path) # :yield: socket addr = Addrinfo.unix(path) sock = addr.connect if block_given? begin yield sock ensure sock.close end else sock end end
Erstellt einen neuen Socket, der über einen UNIX-Socket mit path verbunden ist.
Wenn ein Block angegeben wird, wird der Block mit dem Socket aufgerufen. Der Wert des Blocks wird zurückgegeben. Der Socket wird geschlossen, wenn diese Methode zurückkehrt.
Wenn kein Block angegeben wird, wird der Socket zurückgegeben.
# talk to /tmp/sock socket. Socket.unix("/tmp/sock") {|sock| t = Thread.new { IO.copy_stream(sock, STDOUT) } IO.copy_stream(STDIN, sock) t.join }
Source
# File ext/socket/lib/socket.rb, line 1626 def self.unix_server_loop(path, &b) # :yield: socket, client_addrinfo unix_server_socket(path) {|serv| accept_loop(serv, &b) } end
Erstellt einen UNIX-Socket-Server auf path. Sie ruft den Block für jeden angenommenen Socket auf.
Wenn host angegeben ist, wird er zusammen mit port verwendet, um die Server-Ports zu bestimmen.
Der Socket wird **nicht** geschlossen, wenn der Block zurückkehrt. Die Anwendung sollte ihn also schließen.
Diese Methode löscht zuerst die Socket-Datei, auf die path verweist, wenn die Datei eine Socket-Datei ist und dem Benutzer der Anwendung gehört. Dies ist nur sicher, wenn das Verzeichnis von path nicht von einem bösartigen Benutzer geändert wird. Verwenden Sie also nicht /tmp/malicious-users-directory/socket. Beachten Sie, dass /tmp/socket und /tmp/your-private-directory/socket sicher sind, unter der Annahme, dass /tmp das Sticky-Bit hat.
# Sequential echo server. # It services only one client at a time. Socket.unix_server_loop("/tmp/sock") {|sock, client_addrinfo| begin IO.copy_stream(sock, sock) ensure sock.close end }
Source
# File ext/socket/lib/socket.rb, line 1564 def self.unix_server_socket(path) unless unix_socket_abstract_name?(path) begin st = File.lstat(path) rescue Errno::ENOENT end if st&.socket? && st.owned? File.unlink path end end s = Addrinfo.unix(path).listen if block_given? begin yield s ensure s.close unless unix_socket_abstract_name?(path) File.unlink path end end else s end end
Erstellt einen UNIX-Server-Socket auf path
Wenn kein Block angegeben wird, gibt sie einen lauschenden Socket zurück.
Wenn ein Block angegeben wird, wird dieser mit dem Socket aufgerufen und der Blockwert zurückgegeben. Wenn der Block beendet wird, wird der Socket geschlossen und die Socket-Datei gelöscht.
socket = Socket.unix_server_socket("/tmp/s") p socket #=> #<Socket:fd 3> p socket.local_address #=> #<Addrinfo: /tmp/s SOCK_STREAM> Socket.unix_server_socket("/tmp/sock") {|s| p s #=> #<Socket:fd 3> p s.local_address #=> # #<Addrinfo: /tmp/sock SOCK_STREAM> }
Source
static VALUE
sock_s_unpack_sockaddr_in(VALUE self, VALUE addr)
{
struct sockaddr_in * sockaddr;
VALUE host;
sockaddr = (struct sockaddr_in*)SockAddrStringValuePtr(addr);
if (RSTRING_LEN(addr) <
(char*)&((struct sockaddr *)sockaddr)->sa_family +
sizeof(((struct sockaddr *)sockaddr)->sa_family) -
(char*)sockaddr)
rb_raise(rb_eArgError, "too short sockaddr");
if (((struct sockaddr *)sockaddr)->sa_family != AF_INET
#ifdef INET6
&& ((struct sockaddr *)sockaddr)->sa_family != AF_INET6
#endif
) {
#ifdef INET6
rb_raise(rb_eArgError, "not an AF_INET/AF_INET6 sockaddr");
#else
rb_raise(rb_eArgError, "not an AF_INET sockaddr");
#endif
}
host = rsock_make_ipaddr((struct sockaddr*)sockaddr, RSTRING_SOCKLEN(addr));
return rb_assoc_new(INT2NUM(ntohs(sockaddr->sin_port)), host);
}
Entpackt sockaddr in Port und IP-Adresse.
sockaddr sollte eine Zeichenkette oder ein Addrinfo für AF_INET/AF_INET6 sein.
sockaddr = Socket.sockaddr_in(80, "127.0.0.1") p sockaddr #=> "\x02\x00\x00P\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" p Socket.unpack_sockaddr_in(sockaddr) #=> [80, "127.0.0.1"]
Source
static VALUE
sock_s_unpack_sockaddr_un(VALUE self, VALUE addr)
{
struct sockaddr_un * sockaddr;
VALUE path;
sockaddr = (struct sockaddr_un*)SockAddrStringValuePtr(addr);
if (RSTRING_LEN(addr) <
(char*)&((struct sockaddr *)sockaddr)->sa_family +
sizeof(((struct sockaddr *)sockaddr)->sa_family) -
(char*)sockaddr)
rb_raise(rb_eArgError, "too short sockaddr");
if (((struct sockaddr *)sockaddr)->sa_family != AF_UNIX) {
rb_raise(rb_eArgError, "not an AF_UNIX sockaddr");
}
if (sizeof(struct sockaddr_un) < (size_t)RSTRING_LEN(addr)) {
rb_raise(rb_eTypeError, "too long sockaddr_un - %ld longer than %d",
RSTRING_LEN(addr), (int)sizeof(struct sockaddr_un));
}
path = rsock_unixpath_str(sockaddr, RSTRING_SOCKLEN(addr));
return path;
}
Entpackt sockaddr in Pfad.
sockaddr sollte eine Zeichenkette oder ein Addrinfo für AF_UNIX sein.
sockaddr = Socket.sockaddr_un("/tmp/sock") p Socket.unpack_sockaddr_un(sockaddr) #=> "/tmp/sock"
Öffentliche Instanzmethoden
Source
static VALUE
sock_accept(VALUE server)
{
union_sockaddr buffer;
socklen_t length = (socklen_t)sizeof(buffer);
VALUE peer = rsock_s_accept(rb_cSocket, server, &buffer.addr, &length);
return rb_assoc_new(peer, rsock_io_socket_addrinfo(peer, &buffer.addr, length));
}
Source
# File ext/socket/lib/socket.rb, line 598 def accept_nonblock(exception: true) __accept_nonblock(exception) end
Nimmt eine eingehende Verbindung mit accept(2) an, nachdem O_NONBLOCK für den zugrundeliegenden Dateideskriptor gesetzt wurde. Sie gibt ein Array zurück, das den angenommenen Socket für die eingehende Verbindung, client_socket, und ein Addrinfo, client_addrinfo, enthält.
Beispiel
# In one script, start this first require 'socket' include Socket::Constants socket = Socket.new(AF_INET, SOCK_STREAM, 0) sockaddr = Socket.sockaddr_in(2200, 'localhost') socket.bind(sockaddr) socket.listen(5) begin # emulate blocking accept client_socket, client_addrinfo = socket.accept_nonblock rescue IO::WaitReadable, Errno::EINTR IO.select([socket]) retry end puts "The client said, '#{client_socket.readline.chomp}'" client_socket.puts "Hello from script one!" socket.close # In another script, start this second require 'socket' include Socket::Constants socket = Socket.new(AF_INET, SOCK_STREAM, 0) sockaddr = Socket.sockaddr_in(2200, 'localhost') socket.connect(sockaddr) socket.puts "Hello from script 2." puts "The server said, '#{socket.readline.chomp}'" socket.close
Siehe Socket#accept für Ausnahmen, die ausgelöst werden können, wenn der Aufruf von accept_nonblock fehlschlägt.
Socket#accept_nonblock kann jede Ausnahme auslösen, die einem accept(2)-Fehler entspricht, einschließlich Errno::EWOULDBLOCK.
Wenn die Ausnahme Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::ECONNABORTED oder Errno::EPROTO ist, wird sie von IO::WaitReadable erweitert. Daher kann IO::WaitReadable verwendet werden, um die Ausnahmen abzufangen, um accept_nonblock erneut zu versuchen.
Durch Angabe des Keyword-Arguments exception auf false können Sie angeben, dass accept_nonblock keine IO::WaitReadable-Ausnahme auslösen soll, sondern das Symbol :wait_readable zurückgeben soll.
Siehe
Source
static VALUE
sock_bind(VALUE sock, VALUE addr)
{
VALUE rai;
rb_io_t *fptr;
SockAddrStringValueWithAddrinfo(addr, rai);
GetOpenFile(sock, fptr);
if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr)) < 0)
rsock_sys_fail_raddrinfo_or_sockaddr("bind(2)", addr, rai);
return INT2FIX(0);
}
Bindet an die angegebene lokale Adresse.
Parameter
-
local_sockaddr- diestructsockaddr, die in einer Zeichenkette oder einemAddrinfo-Objekt enthalten ist
Beispiel
require 'socket' # use Addrinfo socket = Socket.new(:INET, :STREAM, 0) socket.bind(Addrinfo.tcp("127.0.0.1", 2222)) p socket.local_address #=> #<Addrinfo: 127.0.0.1:2222 TCP> # use struct sockaddr include Socket::Constants socket = Socket.new( AF_INET, SOCK_STREAM, 0 ) sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' ) socket.bind( sockaddr )
Unix-basierte Ausnahmen
Auf Unix-basierten Systemen können die folgenden Systemausnahmen ausgelöst werden, wenn der Aufruf von bind fehlschlägt
-
Errno::EACCES - die angegebene sockaddr ist geschützt und der aktuelle Benutzer hat keine Berechtigung, sich damit zu verbinden
-
Errno::EADDRINUSE - die angegebene sockaddr wird bereits verwendet
-
Errno::EADDRNOTAVAIL - die angegebene sockaddr ist auf dem lokalen Rechner nicht verfügbar
-
Errno::EAFNOSUPPORT - die angegebene sockaddr ist keine gültige Adresse für die Familie des aufrufenden
socket -
Errno::EBADF - die sockaddr ist kein gültiger Dateideskriptor
-
Errno::EFAULT - das sockaddr-Argument kann nicht zugegriffen werden
-
Errno::EINVAL - der
socketist bereits an eine Adresse gebunden, und das Protokoll unterstützt keine Bindung an die neue sockaddr oder dersocketwurde heruntergefahren. -
Errno::EINVAL - die Adresslänge ist keine gültige Länge für die Adressfamilie
-
Errno::ENAMETOOLONG - der aufgelöste Pfadname hatte eine Länge, die PATH_MAX überschritt
-
Errno::ENOBUFS - kein Pufferplatz verfügbar
-
Errno::ENOSR - es standen nicht genügend STREAMS-Ressourcen zur Verfügung, um den Vorgang abzuschließen
-
Errno::ENOTSOCK - der
socketbezieht sich nicht auf einen Socket -
Errno::EOPNOTSUPP - der Socket-Typ des
socketunterstützt keine Bindung an eine Adresse
Auf Unix-basierten Systemen, wenn die Adressfamilie des aufrufenden socket Socket::AF_UNIX ist, können die folgenden Ausnahmen ausgelöst werden, wenn der Aufruf von bind fehlschlägt
-
Errno::EACCES - Suchberechtigung wird für eine Komponente des Präfixpfads verweigert oder Schreibzugriff auf den
socketwird verweigert -
Errno::EDESTADDRREQ - das sockaddr-Argument ist ein Nullzeiger
-
Errno::EISDIR - wie Errno::EDESTADDRREQ
-
Errno::EIO - ein E/A-Fehler ist aufgetreten
-
Errno::ELOOP - zu viele symbolische Links wurden beim Übersetzen des Pfadnamens in sockaddr angetroffen
-
Errno::ENAMETOOLLONG - eine Komponente eines Pfadnamens überschritt NAME_MAX Zeichen oder ein gesamter Pfadname überschritt PATH_MAX Zeichen
-
Errno::ENOENT - eine Komponente des Pfadnamens benennt keine vorhandene Datei oder der Pfadname ist eine leere Zeichenkette
-
Errno::ENOTDIR - eine Komponente des Pfadpräfixes des Pfadnamens in sockaddr ist kein Verzeichnis
-
Errno::EROFS - der Name würde auf einem schreibgeschützten Dateisystem liegen
Windows-Ausnahmen
Auf Windows-Systemen können die folgenden Systemausnahmen ausgelöst werden, wenn der Aufruf von bind fehlschlägt
-
Errno::ENETDOWN - das Netzwerk ist ausgefallen
-
Errno::EACCES - der Versuch, den Datagramm-Socket an die Broadcast-Adresse zu binden, schlug fehl
-
Errno::EADDRINUSE - die lokale Adresse des Sockets wird bereits verwendet
-
Errno::EADDRNOTAVAIL - die angegebene Adresse ist keine gültige Adresse für diesen Computer
-
Errno::EFAULT - der interne Adress- oder Adresslängenparameter des Sockets ist zu klein oder kein gültiger Teil des adressierten Benutzerraums
-
Errno::EINVAL - der
socketist bereits an eine Adresse gebunden -
Errno::ENOBUFS - kein Pufferplatz verfügbar
-
Errno::ENOTSOCK - das
socket-Argument bezieht sich nicht auf einen Socket
Siehe
-
Bindungs-Handbücher auf Unix-basierten Systemen
-
Bindungsfunktion in Microsofts Winsock-Funktionsreferenz
Source
static VALUE
sock_connect(VALUE self, VALUE addr)
{
VALUE rai;
SockAddrStringValueWithAddrinfo(addr, rai);
addr = rb_str_new4(addr);
int result = rsock_connect(self, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0, RUBY_IO_TIMEOUT_DEFAULT);
if (result < 0) {
rsock_sys_fail_raddrinfo_or_sockaddr("connect(2)", addr, rai);
}
return INT2FIX(result);
}
Fordert eine Verbindung zu remote_sockaddr an. Gibt 0 zurück, wenn erfolgreich, andernfalls wird eine Ausnahme ausgelöst.
Parameter
-
remote_sockaddr- diestructsockaddr, die in einer Zeichenkette oder einemAddrinfo-Objekt enthalten ist
Beispiel
# Pull down Google's web page require 'socket' include Socket::Constants socket = Socket.new( AF_INET, SOCK_STREAM, 0 ) sockaddr = Socket.pack_sockaddr_in( 80, 'www.google.com' ) socket.connect( sockaddr ) socket.write( "GET / HTTP/1.0\r\n\r\n" ) results = socket.read
Unix-basierte Ausnahmen
Auf Unix-basierten Systemen können die folgenden Systemausnahmen ausgelöst werden, wenn der Aufruf von connect fehlschlägt
-
Errno::EACCES - Suchberechtigung wird für eine Komponente des Präfixpfads verweigert oder Schreibzugriff auf den
socketwird verweigert -
Errno::EADDRINUSE - die sockaddr wird bereits verwendet
-
Errno::EADDRNOTAVAIL - die angegebene sockaddr ist auf dem lokalen Rechner nicht verfügbar
-
Errno::EAFNOSUPPORT - die angegebene sockaddr ist keine gültige Adresse für die Adressfamilie des angegebenen
socket -
Errno::EALREADY - eine Verbindung wird für den angegebenen Socket bereits hergestellt
-
Errno::EBADF - der
socketist kein gültiger Dateideskriptor -
Errno::ECONNREFUSED - die Ziel-sockaddr hörte nicht auf Verbindungen und lehnte die Verbindungsanforderung ab
-
Errno::ECONNRESET - der Remote-Host hat die Verbindungsanforderung zurückgesetzt
-
Errno::EFAULT - die sockaddr kann nicht zugegriffen werden
-
Errno::EHOSTUNREACH - der Zielhost ist nicht erreichbar (wahrscheinlich, weil der Host ausgefallen ist oder ein entfernter Router ihn nicht erreichen kann)
-
Errno::EINPROGRESS - O_NONBLOCK ist für den
socketgesetzt und die Verbindung kann nicht sofort hergestellt werden; die Verbindung wird asynchron hergestellt -
Errno::EINTR - der Versuch, die Verbindung herzustellen, wurde durch die Zustellung eines abgefangenen Signals unterbrochen; die Verbindung wird asynchron hergestellt
-
Errno::EISCONN - der angegebene
socketist bereits verbunden -
Errno::EINVAL - die für die sockaddr verwendete Adresslänge ist keine gültige Länge für die Adressfamilie oder es gibt eine ungültige Familie in sockaddr
-
Errno::ENAMETOOLONG - der aufgelöste Pfadname hatte eine Länge, die PATH_MAX überschritt
-
Errno::ENETDOWN - die lokale Schnittstelle, die zum Erreichen des Ziels verwendet wird, ist ausgefallen
-
Errno::ENETUNREACH - kein Pfad zum Netzwerk vorhanden
-
Errno::ENOBUFS - kein Pufferplatz verfügbar
-
Errno::ENOSR - es standen nicht genügend STREAMS-Ressourcen zur Verfügung, um den Vorgang abzuschließen
-
Errno::ENOTSOCK - das
socket-Argument bezieht sich nicht auf einen Socket -
Errno::EOPNOTSUPP - der aufrufende
socketlauscht und kann nicht verbunden werden -
Errno::EPROTOTYPE - die sockaddr hat einen anderen Typ als der Socket, der an die angegebene Peer-Adresse gebunden ist
-
Errno::ETIMEDOUT - der Verbindungsversuch ist fehlgeschlagen, bevor eine Verbindung hergestellt wurde.
Auf Unix-basierten Systemen, wenn die Adressfamilie des aufrufenden socket AF_UNIX ist, können die folgenden Ausnahmen ausgelöst werden, wenn der Aufruf von connect fehlschlägt
-
Errno::EIO - ein E/A-Fehler ist beim Lesen oder Schreiben des Dateisystems aufgetreten
-
Errno::ELOOP - zu viele symbolische Links wurden beim Übersetzen des Pfadnamens in sockaddr angetroffen
-
Errno::ENAMETOOLLONG - eine Komponente eines Pfadnamens überschritt NAME_MAX Zeichen oder ein gesamter Pfadname überschritt PATH_MAX Zeichen
-
Errno::ENOENT - eine Komponente des Pfadnamens benennt keine vorhandene Datei oder der Pfadname ist eine leere Zeichenkette
-
Errno::ENOTDIR - eine Komponente des Pfadpräfixes des Pfadnamens in sockaddr ist kein Verzeichnis
Windows-Ausnahmen
Auf Windows-Systemen können die folgenden Systemausnahmen ausgelöst werden, wenn der Aufruf von connect fehlschält
-
Errno::ENETDOWN - das Netzwerk ist ausgefallen
-
Errno::EADDRINUSE - die lokale Adresse des Sockets wird bereits verwendet
-
Errno::EINTR - der Socket wurde abgebrochen
-
Errno::EINPROGRESS - ein blockierender Socket wird verarbeitet oder der Dienstanbieter verarbeitet noch eine Callback-Funktion. Oder ein nicht-blockierender Verbindungsaufruf wird auf dem
socketdurchgeführt. -
Errno::EALREADY - siehe Errno::EINVAL
-
Errno::EADDRNOTAVAIL - die Remote-Adresse ist keine gültige Adresse, wie ADDR_ANY TODO check ADDRANY TO
INADDR_ANY -
Errno::EAFNOSUPPORT - Adressen in der angegebenen Familie können nicht mit diesem
socketverwendet werden -
Errno::ECONNREFUSED - die Ziel-sockaddr hörte nicht auf Verbindungen und lehnte die Verbindungsanforderung ab
-
Errno::EFAULT - der interne Adress- oder Adresslängenparameter des Sockets ist zu klein oder kein gültiger Teil des adressierten Benutzerraums
-
Errno::EINVAL - der
socketist ein lauschender Socket -
Errno::EISCONN - der
socketist bereits verbunden -
Errno::ENETUNREACH - das Netzwerk ist von diesem Host derzeit nicht erreichbar
-
Errno::EHOSTUNREACH - kein Pfad zum Netzwerk vorhanden
-
Errno::ENOBUFS - kein Pufferplatz verfügbar
-
Errno::ENOTSOCK - das
socket-Argument bezieht sich nicht auf einen Socket -
Errno::ETIMEDOUT - der Verbindungsversuch ist fehlgeschlagen, bevor eine Verbindung hergestellt wurde.
-
Errno::EWOULDBLOCK - der Socket ist als nicht-blockierend markiert und die Verbindung kann nicht sofort hergestellt werden
-
Errno::EACCES - der Versuch, den Datagramm-Socket an die Broadcast-Adresse zu binden, schlug fehl
Siehe
-
Connect-Handbücher auf Unix-basierten Systemen
-
Connect-Funktion in Microsofts Winsock-Funktionsreferenz
Source
# File ext/socket/lib/socket.rb, line 1676 def connect_nonblock(addr, exception: true) __connect_nonblock(addr, exception) end
Fordert eine Verbindung zu remote_sockaddr an, nachdem O_NONBLOCK für den zugrundeliegenden Dateideskriptor gesetzt wurde. Gibt 0 zurück, wenn erfolgreich, andernfalls wird eine Ausnahme ausgelöst.
Parameter
-
remote_sockaddr- diestructsockaddr, die in einer Zeichenkette oder einemAddrinfo-Objekt enthalten ist
Beispiel
# Pull down Google's web page require 'socket' include Socket::Constants socket = Socket.new(AF_INET, SOCK_STREAM, 0) sockaddr = Socket.sockaddr_in(80, 'www.google.com') begin # emulate blocking connect socket.connect_nonblock(sockaddr) rescue IO::WaitWritable IO.select(nil, [socket]) # wait 3-way handshake completion begin socket.connect_nonblock(sockaddr) # check connection failure rescue Errno::EISCONN end end socket.write("GET / HTTP/1.0\r\n\r\n") results = socket.read
Siehe Socket#connect für Ausnahmen, die ausgelöst werden können, wenn der Aufruf von connect_nonblock fehlschlägt.
Socket#connect_nonblock kann jede Ausnahme auslösen, die einem connect(2)-Fehler entspricht, einschließlich Errno::EINPROGRESS.
Wenn die Ausnahme Errno::EINPROGRESS ist, wird sie von IO::WaitWritable erweitert. Daher kann IO::WaitWritable verwendet werden, um die Ausnahmen abzufangen, um connect_nonblock erneut zu versuchen.
Durch Angabe des Keyword-Arguments exception auf false können Sie angeben, dass connect_nonblock keine IO::WaitWritable-Ausnahme auslösen soll, sondern das Symbol :wait_writable zurückgeben soll.
Siehe
Source
# File ext/socket/lib/socket.rb, line 468 def ipv6only! if defined? Socket::IPV6_V6ONLY self.setsockopt(:IPV6, :V6ONLY, 1) end end
aktiviert die Socket-Option IPV6_V6ONLY, falls IPV6_V6ONLY verfügbar ist.
Source
VALUE
rsock_sock_listen(VALUE sock, VALUE log)
{
rb_io_t *fptr;
int backlog;
backlog = NUM2INT(log);
GetOpenFile(sock, fptr);
if (listen(fptr->fd, backlog) < 0)
rb_sys_fail("listen(2)");
return INT2FIX(0);
}
Lauscht auf Verbindungen und verwendet die angegebene int als Backlog. Ein Aufruf von listen ist nur anwendbar, wenn der socket vom Typ SOCK_STREAM oder SOCK_SEQPACKET ist.
Parameter
-
backlog- die maximale Länge der Warteschlange für ausstehende Verbindungen.
Beispiel 1
require 'socket' include Socket::Constants socket = Socket.new( AF_INET, SOCK_STREAM, 0 ) sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' ) socket.bind( sockaddr ) socket.listen( 5 )
Beispiel 2 (lauscht auf einem beliebigen Port, nur Unix-basierte Systeme)
require 'socket' include Socket::Constants socket = Socket.new( AF_INET, SOCK_STREAM, 0 ) socket.listen( 1 )
Unix-basierte Ausnahmen
Auf Unix-basierten Systemen funktioniert dies, da eine neue sockaddr-Struktur für die Adresse ADDR_ANY für eine beliebige Portnummer erstellt wird, die vom Kernel zugewiesen wird. Unter Windows funktioniert dies nicht, da unter Windows der socket durch Aufruf von bind gebunden sein muss, bevor er listen kann.
Wenn die backlog-Menge die implementierungsabhängige maximale Warteschlangenlänge überschreitet, wird die maximale Warteschlangenlänge der Implementierung verwendet.
Auf Unix-basierten Systemen können die folgenden Systemausnahmen ausgelöst werden, wenn der Aufruf von listen fehlschlägt
-
Errno::EBADF - das socket-Argument ist kein gültiger Dateideskriptor
-
Errno::EDESTADDRREQ - der socket ist nicht an eine lokale Adresse gebunden, und das Protokoll unterstützt kein Lauschen auf einem ungebundenen Socket
-
Errno::EINVAL - der socket ist bereits verbunden
-
Errno::ENOTSOCK - das socket-Argument bezieht sich nicht auf einen Socket
-
Errno::EOPNOTSUPP - das socket-Protokoll unterstützt listen nicht
-
Errno::EACCES - der aufrufende Prozess hat keine geeigneten Berechtigungen
-
Errno::EINVAL - der socket wurde heruntergefahren
-
Errno::ENOBUFS - es stehen nicht genügend Systemressourcen zur Verfügung, um den Aufruf abzuschließen
Windows-Ausnahmen
Auf Windows-Systemen können die folgenden Systemausnahmen ausgelöst werden, wenn der Aufruf von listen fehlschlägt
-
Errno::ENETDOWN - das Netzwerk ist ausgefallen
-
Errno::EADDRINUSE - die lokale Adresse des Sockets ist bereits in Verwendung. Dies tritt normalerweise während der Ausführung von bind auf, kann aber verzögert werden, wenn der Aufruf von bind an eine teilweise Wildcard-Adresse (einschließlich ADDR_ANY) erfolgte und eine bestimmte Adresse zum Zeitpunkt des Aufrufs von listen zugewiesen werden muss.
-
Errno::EINPROGRESS - ein Windows Sockets 1.1-Aufruf ist in Bearbeitung oder der Dienstanbieter verarbeitet noch eine Callback-Funktion.
-
Errno::EINVAL - der
socketwurde nicht mit einem Aufruf von bind gebunden. -
Errno::EISCONN - der
socketist bereits verbunden -
Errno::EMFILE - keine Socket-Deskriptoren mehr verfügbar.
-
Errno::ENOBUFS - kein Pufferplatz verfügbar
-
Errno::ENOTSOC -
socketist kein Socket. -
Errno::EOPNOTSUPP - der referenzierte
socketist kein Typ, der die listen-Methode unterstützt.
Siehe
-
listen-Manpages auf Unix-basierten Systemen.
-
listen-Funktion in der Microsoft Winsock-Funktionsreferenz.
Source
static VALUE
sock_recvfrom(int argc, VALUE *argv, VALUE sock)
{
return rsock_s_recvfrom(sock, argc, argv, RECV_SOCKET);
}
Empfängt bis zu maxlen Bytes vom socket. flags ist null oder mehr der MSG_-Optionen. Das erste Element der Ergebnisse, mesg, sind die empfangenen Daten. Das zweite Element, sender_addrinfo, enthält protokollspezifische Adressinformationen des Absenders.
Parameter
-
maxlen- die maximale Anzahl von Bytes, die vom Socket empfangen werden sollen. -
flags- null oder mehr derMSG_-Optionen.
Beispiel
# In one file, start this first require 'socket' include Socket::Constants socket = Socket.new( AF_INET, SOCK_STREAM, 0 ) sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' ) socket.bind( sockaddr ) socket.listen( 5 ) client, client_addrinfo = socket.accept data = client.recvfrom( 20 )[0].chomp puts "I only received 20 bytes '#{data}'" sleep 1 socket.close # In another file, start this second require 'socket' include Socket::Constants socket = Socket.new( AF_INET, SOCK_STREAM, 0 ) sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' ) socket.connect( sockaddr ) socket.puts "Watch this get cut short!" socket.close
Unix-basierte Ausnahmen
Auf Unix-basierten Systemen können folgende Systemausnahmen ausgelöst werden, wenn der Aufruf von recvfrom fehlschlägt:
-
Errno::EAGAIN - der
socket-Dateideskriptor ist als O_NONBLOCK markiert und es warten keine Daten zum Empfang; oderMSG_OOBist gesetzt und es sind keine Out-of-Band-Daten verfügbar und entweder ist dersocket-Dateideskriptor als O_NONBLOCK markiert oder dersocketunterstützt kein Blockieren, um auf Out-of-Band-Daten zu warten. -
Errno::EWOULDBLOCK - siehe Errno::EAGAIN.
-
Errno::EBADF - der
socketist kein gültiger Dateideskriptor -
Errno::ECONNRESET - eine Verbindung wurde von einem Peer zwangsweise geschlossen.
-
Errno::EFAULT - der interne Puffer, die Adresse oder die Adresslänge des Sockets können nicht zugegriffen oder geschrieben werden.
-
Errno::EINTR - ein Signal hat recvfrom unterbrochen, bevor Daten verfügbar waren.
-
Errno::EINVAL - das Flag
MSG_OOBist gesetzt und es sind keine Out-of-Band-Daten verfügbar. -
Errno::EIO - ein E/A-Fehler ist beim Lesen von oder Schreiben auf das Dateisystem aufgetreten.
-
Errno::ENOBUFS - nicht genügend Ressourcen im System verfügbar, um die Operation auszuführen.
-
Errno::ENOMEM - nicht genügend Speicher verfügbar, um die Anfrage zu erfüllen.
-
Errno::ENOSR - es standen nicht genügend STREAMS-Ressourcen zur Verfügung, um den Vorgang abzuschließen
-
Errno::ENOTCONN - ein Empfang wird auf einem Connection-Mode-Socket versucht, der nicht verbunden ist.
-
Errno::ENOTSOCK - der
socketbezieht sich nicht auf einen Socket -
Errno::EOPNOTSUPP - die angegebenen Flags werden für diesen Socket-Typ nicht unterstützt.
-
Errno::ETIMEDOUT - die Verbindung ist während des Verbindungsaufbaus oder aufgrund eines Übertragungs-Timeouts bei einer aktiven Verbindung abgelaufen.
Windows-Ausnahmen
Unter Windows-Systemen können folgende Systemausnahmen ausgelöst werden, wenn der Aufruf von recvfrom fehlschlägt:
-
Errno::ENETDOWN - das Netzwerk ist ausgefallen
-
Errno::EFAULT - der interne Puffer und die 'from'-Parameter im
socketsind nicht Teil des Benutzeradressraums, oder der interne 'fromlen'-Parameter ist zu klein, um die Peer-Adresse aufzunehmen. -
Errno::EINTR - der (blockierende) Aufruf wurde durch einen internen Aufruf der WinSock-Funktion WSACancelBlockingCall abgebrochen.
-
Errno::EINPROGRESS - ein blockierender Windows Sockets 1.1-Aufruf ist in Bearbeitung oder der Dienstanbieter verarbeitet noch eine Callback-Funktion.
-
Errno::EINVAL -
socketwurde nicht mit einem Aufruf von bind gebunden, oder es wurde ein unbekanntes Flag angegeben, oderMSG_OOBwurde für einen Socket mit aktiviertemSO_OOBINLINEangegeben, oder (nur für Byte-Stream-Sockets) der interne 'len'-Parameter imsocketwar null oder negativ. -
Errno::EISCONN -
socketist bereits verbunden. Der Aufruf von recvfrom ist mit einem verbundenen Socket für einen verbindungsorientierten oder verbindungsfreien Socket nicht zulässig. -
Errno::ENETRESET - die Verbindung wurde aufgrund von Keep-Alive-Aktivitäten, die einen Fehler während der Ausführung der Operation erkannten, unterbrochen.
-
Errno::EOPNOTSUPP -
MSG_OOBwurde angegeben, abersocketist kein Stream-Typ wie z.B.SOCK_STREAM. OOB-Daten werden in der Kommunikationsdomäne, die mitsocketassoziiert ist, nicht unterstützt, odersocketist unidirektional und unterstützt nur Sendeoperationen. -
Errno::ESHUTDOWN -
socketwurde heruntergefahren. Es ist nicht möglich, recvfrom auf einem Socket aufzurufen, nachdem shutdown aufgerufen wurde. -
Errno::EWOULDBLOCK -
socketist als nicht blockierend markiert und ein Aufruf von recvfrom würde blockieren. -
Errno::EMSGSIZE - die Nachricht war zu groß, um in den angegebenen Puffer zu passen, und wurde abgeschnitten.
-
Errno::ETIMEDOUT - die Verbindung wurde aufgrund eines Netzwerkausfalls oder weil das System auf der anderen Seite ohne Vorwarnung heruntergefahren ist, unterbrochen worden.
-
Errno::ECONNRESET - die virtuelle Verbindung wurde von der Remote-Seite durch einen Hard- oder Abort-Close zurückgesetzt. Die Anwendung sollte den Socket schließen; er ist nicht mehr verwendbar. Bei einem UDP-Datagramm-Socket bedeutet dieser Fehler, dass eine vorherige Sendeoperation zu einer ICMP Port Unreachable-Nachricht geführt hat.
Source
# File ext/socket/lib/socket.rb, line 541 def recvfrom_nonblock(len, flag = 0, str = nil, exception: true) __recvfrom_nonblock(len, flag, str, exception) end
Empfängt bis zu maxlen Bytes vom socket mit recvfrom(2), nachdem O_NONBLOCK für den zugrundeliegenden Dateideskriptor gesetzt wurde. flags ist null oder mehr der MSG_-Optionen. Das erste Element der Ergebnisse, mesg, sind die empfangenen Daten. Das zweite Element, sender_addrinfo, enthält protokollspezifische Adressinformationen des Absenders.
Wenn recvfrom(2) 0 zurückgibt, gibt Socket#recv_nonblock nil zurück. In den meisten Fällen bedeutet dies, dass die Verbindung geschlossen wurde, aber bei UDP-Verbindungen kann dies bedeuten, dass ein leeres Paket empfangen wurde, da die zugrunde liegende API es unmöglich macht, diese beiden Fälle zu unterscheiden.
Parameter
-
maxlen- die maximale Anzahl von Bytes, die vom Socket empfangen werden sollen. -
flags- null oder mehr derMSG_-Optionen. -
outbuf- Ziel-String-Puffer (String). -
opts- Schlüsselwort-Hash, unterstützt 'exception: false'.
Beispiel
# In one file, start this first require 'socket' include Socket::Constants socket = Socket.new(AF_INET, SOCK_STREAM, 0) sockaddr = Socket.sockaddr_in(2200, 'localhost') socket.bind(sockaddr) socket.listen(5) client, client_addrinfo = socket.accept begin # emulate blocking recvfrom pair = client.recvfrom_nonblock(20) rescue IO::WaitReadable IO.select([client]) retry end data = pair[0].chomp puts "I only received 20 bytes '#{data}'" sleep 1 socket.close # In another file, start this second require 'socket' include Socket::Constants socket = Socket.new(AF_INET, SOCK_STREAM, 0) sockaddr = Socket.sockaddr_in(2200, 'localhost') socket.connect(sockaddr) socket.puts "Watch this get cut short!" socket.close
Beachten Sie Socket#recvfrom für die Ausnahmen, die ausgelöst werden können, wenn der Aufruf von recvfrom_nonblock fehlschlägt.
Socket#recvfrom_nonblock kann jede Ausnahme auslösen, die einem recvfrom(2)-Fehler entspricht, einschließlich Errno::EWOULDBLOCK.
Wenn die Ausnahme Errno::EWOULDBLOCK oder Errno::EAGAIN ist, wird sie durch IO::WaitReadable erweitert. Daher kann IO::WaitReadable verwendet werden, um die Ausnahmen für das erneute Versuchen von recvfrom_nonblock abzufangen.
Durch Angabe des Schlüsselwortarguments exception mit dem Wert false können Sie angeben, dass recvfrom_nonblock keine IO::WaitReadable-Ausnahme auslösen soll, sondern das Symbol :wait_readable zurückgeben soll.
Siehe
Source
static VALUE
sock_sysaccept(VALUE server)
{
union_sockaddr buffer;
socklen_t length = (socklen_t)sizeof(buffer);
VALUE peer = rsock_s_accept(0, server, &buffer.addr, &length);
return rb_assoc_new(peer, rsock_io_socket_addrinfo(peer, &buffer.addr, length));
}
Akzeptiert eine eingehende Verbindung und gibt ein Array zurück, das den (Integer-)Dateideskriptor für die eingehende Verbindung, client_socket_fd, und eine Addrinfo, client_addrinfo, enthält.
Beispiel
# In one script, start this first require 'socket' include Socket::Constants socket = Socket.new( AF_INET, SOCK_STREAM, 0 ) sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' ) socket.bind( sockaddr ) socket.listen( 5 ) client_fd, client_addrinfo = socket.sysaccept client_socket = Socket.for_fd( client_fd ) puts "The client said, '#{client_socket.readline.chomp}'" client_socket.puts "Hello from script one!" socket.close # In another script, start this second require 'socket' include Socket::Constants socket = Socket.new( AF_INET, SOCK_STREAM, 0 ) sockaddr = Socket.pack_sockaddr_in( 2200, 'localhost' ) socket.connect( sockaddr ) socket.puts "Hello from script 2." puts "The server said, '#{socket.readline.chomp}'" socket.close
Beachten Sie Socket#accept für die Ausnahmen, die ausgelöst werden können, wenn der Aufruf von sysaccept fehlschlägt.