|
Class: Socket
Object
|
+--Stream
|
+--PeekableStream
|
+--PositionableStream
|
+--WriteStream
|
+--ReadWriteStream
|
+--ExternalStream
|
+--NonPositionableExternalStream
|
+--Socket
- Package:
- stx:libbasic2
- Category:
- Streams-External
- Version:
- rev:
1.440
date: 2024/02/19 14:13:49
- user: cg
- file: Socket.st directory: libbasic2
- module: stx stc-classLibrary: libbasic2
This class provides access to sockets for interprocess communication.
Currently, only IP and UNIX domain sockets are really fully
tested and supported.
Code for appletalk is included, but was never tested ...
More may be added in the future.
(the code is prepared for things like SNA or decNet;
however, right now, this code is empty and needs a little work.
Implementing those is pretty straightforward, once the address
data structures are known.)
Due to historic reasons (I started this class, before I got hold of some
code using ST-80 Sockets i.e. RemoteInvocation), there is some old interface
which is still supported.
This may vanish; use the #family:type: or #newTCPxxx and #newUDPxxx interfaces,
together with the bind/listen and accept calls,
which are meant to be compatible to ST-80's UnixSocketAccessor interface.
TODO: cleanup historic leftovers,
change to raise more signals on errors.
copyrightCOPYRIGHT (c) 1992 by Claus Gittinger
All Rights Reserved
This software is furnished under a license and may be used
only in accordance with the terms of that license and with the
inclusion of the above copyright notice. This software may not
be provided or otherwise made available to, or used by, any
other person. No title to or ownership of the software is
hereby transferred.
Compatibility-ST80
-
family: domainSymbol type: typeSymbol
-
create a socket for domain and type - ST80 simply uses a different name.
Domain must be one of the symbols: #inet, #unix, #appletalk or #ns;
Type must be #stream, #datagram or #raw.
Usage example(s):
Socket family:#AF_INET type:#stream
Socket family:#AF_INET type:#datagram
Socket family:#AF_UNIX type:#stream
|
-
getHostname
-
return the computer's hostname string
-
sockStream
-
return the type code for stream sockets
Compatibility-Squeak
-
deadlineSecs: numSeconds
-
return a timestamp numSeconds from now
-
initializeNetwork
-
intentionally left blank here
-
openConnectionToHostNamed: hostName port: portNr
-
-
standardDeadline
-
a standard timeout in seconds for connection setup;
not really used in ST/X code (but by some code ported from squeak)
-
standardTimeout
-
a standard timeout in seconds for transfers;
not really used in ST/X code (but by some code ported from squeak)
-
wildcardPort
-
Compatibility-VW
-
AF_INET
-
-
SOCK_STREAM
-
Signal constants
-
brokenConnectionSignal
-
return the signal used to tell broken connections.
Since in unix, this is the same as the broken pipe signal,
return that one.
(for other Operatingsystems, this may change ..)
-
invalidArgumentsSignal
-
dummy for compatibility
debugging
-
debug: aBoolean
-
turn on/off internal debugprints.
This method is for ST/X debugging only and
may be removed without notice in later versions
Usage example(s):
Socket debug:true
Socket debug:false
|
-
defaultConnectTimeout
-
-
defaultConnectTimeout: secondsOrTimeDuration
-
defaults
-
defaultIpDomainForConnect
-
answer the domain used to look up host names for connect:
#AF_INET use only IPv4
#AF_INET6 use only IPv6
nil use both IPv4 and IPv6
-
defaultIpDomainOrderForConnect
-
answer the order of inet domains when trying to connect:
#AF_INET IPv4
#AF_INET6 IPv6
instance creation
-
bindTo: aSocketAddress type: aTypeSymbol
-
create a socket for a specific type
and bind it to aSocketAddress.
Type must be:
#stream, #datagram or #raw
Neither connect nor connect-wait is done.
Usage example(s):
Socket bindTo:(IPSocketAddress anyHost port:8081) type:#stream.
Socket bindTo:(IPv6SocketAddress anyHost port:8081) type:#datagram.
|
-
domain: domainSymbol type: type
-
create a socket for domain and type -
neither any connect nor binding is done.
Domain must be one of the symbols:
#inet, #unix, #appletalk, #decnet, #xns, ...;
Type must be:
#stream, #datagram or #raw
XXX: currently only the #AF_INET and #AF_INET6 and #AF_UNIX domains are supported
Usage example(s):
Socket domain:#AF_INET type:#stream
Socket domain:#AF_INET type:#datagram
Socket domain:#AF_INET6 type:#stream
Socket domain:#AF_INET6 type:#datagram
Socket domain:#AF_UNIX type:#stream
|
-
newTCP
-
marked as obsolete by Stefan Vogel at 17-Aug-2022
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
newTCP: portNrOrServiceName
-
create a IPv4 TCP socket for a service -
neither connect nor connect-wait is done.
OBSOLETE, since not compatible with IPv6!
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
newTCP: portNrOrServiceName useIPv6: useIPv6
-
create a TCP socket for a service -
neither connect nor connect-wait is done.
If portNrOrServiceName is non-nil, bind to the port.
If portNrOrServiceName is 0, bind to an unused port allocated by the OS.
If portNrOrServiceName is nil, do not bind.
Usage example(s):
Socket newTCP:'http-alt'.
Socket newTCP:9996 useIPv6:false.
Socket newTCP:9996 useIPv6:true.
|
-
newTCPclientToAddress: aHostAddress port: aService
-
create a new TCP client socket connecting to a service.
Return a socket instance if ok, nil on failure.
Block until a connection is established (but only the current thread;
not the whole smalltalk).
See also: #newTCPclientToAddress:port:withTimeout:
-
newTCPclientToAddress: aSocketAddressOrByteArray port: aService withTimeout: milliSecondsOrTimeDuration
-
create a new TCP client socket connecting to a service.
Return a socket instance if ok, nil on failure.
If the millis arg is nonNil, stop trying to connect after that many milliseconds
and return nil.
-
newTCPclientToAddress: aSocketAddress withTimeout: milliSecondsOrTimeDuration
-
create a new TCP client socket connecting to a service.
Return a socket instance if ok, nil on failure.
If the millis arg is nonNil, stop trying to connect after that many milliseconds
and return nil.
Usage example(s):
self newTCPclientToAddress:(IPv6SocketAddress hostName:'www.exept.de' port:80) withTimeout:nil
|
-
newTCPclientToHost: hostNameOrAddress port: aPortOrServiceName
-
create a new TCP client socket connecting to a service.
If hostNameOrAddress is a string, try all the resolved addresses regardless
whether for IPv4 or IPv6.
Return a socket instance if ok, nil on failure.
Block until a connection is established (but only the current thread;
not the whole smalltalk).
See also: #newTCPclientToHost:port:withTimeout:
Usage example(s):
Socket newTCPclientToHost:'www.exept.de' port:'https'
|
-
newTCPclientToHost: hostNameOrAddress port: aPortOrServiceName domain: aDomainSymbolOrNil domainOrder: orderOrNil withTimeout: milliSecondsOrTimeDuration
-
create a new TCP client socket connecting to a service on hostNameOrAddress.
If hostNameOrAddress is a string, try all the resolved addresses.
Set aDomainSymbolOrNil to #AF_INET of #AF_INET6 to connect via a defined protocol.
Set aDomainSymbolOrNil to nil, to try all protocols.
orderOrNil may be a list of domain symbols or nil.
if not nil, the attempts to establish a connection fo the different domains is
done in this order.
If the milliSecondsOrTimeDuration arg is nonNil,
stop trying to connect after that many milliSecondsOrTimeDuration
and return nil.
Return a socket instance if ok.
On failure raise a SocketErrorNotification (which is ignored if not handled)
and return nil.
-
newTCPclientToHost: hostNameOrAddress port: aPortOrServiceName domain: aDomainSymbolOrNil withTimeout: milliSecondsOrTimeDuration
-
create a new TCP client socket connecting to a service on hostNameOrAddress.
If hostNameOrAddress is a string, try all the resolved addresses.
Return a socket instance if ok.
On failure raise a SocketErrorNotification (which is ignored if not handled)
and return nil.
Set aDomainSymbolOrNil to #AF_INET of #AF_INET6 to connect via a defined protocol.
Set aDomainSymbolOrNil to nil, to try all protocols as defined in #defaultIpDomainOrderForConnect.
If the milliSecondsOrTimeDuration arg is nonNil, stop trying to connect after that many milliSecondsOrTimeDurationeconds
and return nil.
-
newTCPclientToHost: hostNameOrAddress port: aPortOrServiceName withTimeout: milliSecondsOrTimeDuration
-
create a new TCP client socket connecting to a service on hostNameOrAddress.
If hostNameOrAddress is a string, try all the resolved addresses regardless
whether for IPv4 or IPv6.
Try all protocols as defined in #defaultIpDomainOrderForConnect.
Return a socket instance if ok.
On failure raise a SocketErrorNotification (which is ignored if not handled)
and return nil.
If the millis arg is nonNil, stop trying to connect after that many milliseconds
and return nil.
-
newTCPserverAtAddress: anIPSocketAddress backlog: backLogCount
-
create a new TCP server socket providing service.
backLogCount is the max number of un-accepted connect requests, that will be queued.
If anIPSocketAddress is an IPv6SocketAddress the connection will both handle both IPv6 and IPv4 connections.
If anIPSocketAddress is an IPSocketAddress (i.e. IPv4) the connection will only handle IPv4 connections.
If the address part of anIPSocketAddress is anyHost (or not set), connections on any interface will be accepted.
If the address part of anIPSocketAddress is a specific IP address, connections only on the interface with this address will be accepted.
If the port of anIPSocketAddress is 0, a unused port will be assigned.
Usage example(s):
An IPv4 Socket on port 5678:
self newTCPserverAtAddress:(IPSocketAddress anyHost port:5678) backlog:1
An IPv4 Socket with an unused port assigned by the OS:
self newTCPserverAtAddress:IPSocketAddress anyHost backlog:1
An IPv6 Socket (also accepting IPv4 connections) with an unused port assigned by the OS:
self newTCPserverAtAddress:IPv6SocketAddress anyHost backlog:1
|
-
newTCPserverAtAnonymousPort
-
create a new TCP server socket providing service on
a new anonymous port. The portNr is assigned by the OS.
-
newTCPserverAtPort: portNrOrServiceName
-
create a new TCP server socket providing service.
-
newUDP
-
marked as obsolete by Stefan Vogel at 17-Aug-2022
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
newUDP: aServiceOrNil
-
create an IPv4 UDP socket for a service -
neither connect nor connect-wait is done.
aServiceOrNil may be the port number or the name of a service.
OBSOLETE, since not compatible with IPv6!
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
newUDP: portNrOrServiceName useIPv6: useIPv6
-
create a UDP socket for a service -
neither connect nor connect-wait is done.
aServiceOrNil may be the port number or the name of a service
Usage example(s):
Socket newUDP:4444 useIPv6:true.
Socket newUDP:4444 useIPv6:false.
Socket newUDP:'activesync' useIPv6:true.
Socket newUDP:0 useIPv6:true.
|
-
newUDPclientToAddress: aSocketAddress
-
create a new UDP client socket connecting to a service
(i.e. set the default address where all packets are sent to).
Return a socket instance if ok, nil on failure.
Usage example(s):
self newUDPclientToAddress:IPSocketAddress localHost.
self newUDPclientToAddress:IPv6SocketAddress localHost.
|
-
newUDPserverAtPort: aService
-
create a new UDP server socket providing service.
-
newUNIX
-
create a UNIX domain socket - no binding or other setup is done,
neither connect nor connect-wait is done.
If the system does not support unix domain sockets (i.e. VMS or MSDOS),
return nil.
Usage example(s):
-
newUNIXclientTo: pathName
-
create a new UNIX client socket connecting to a pathname.
Return a socket instance if ok, nil on failure.
Block until a connection is established (but only the current thread;
not the whole smalltalk).
If the system does not support unix domain sockets (i.e. VMS or MSDOS),
return nil.
See also: #newUNIXclientTo:withTimeout:
-
newUNIXclientTo: pathName withTimeout: milliSecondsOrTimeDuration
-
create a new UNIX client socket connecting to a pathname.
Return a socket instance if ok, nil on failure.
If the millis arg is nonNil, stop trying to connect after that many milliseconds
and return nil.
If the system does not support unix domain sockets (i.e. VMS or MSDOS),
return nil.
Usage example(s):
Socket newUNIXclientTo:'/tmp/foo'
[
Socket newUNIXclientTo:'/tmp/foo'
] on:SocketErrorNotification do:[:ex|
ex halt.
]
|
-
newUNIXserverAt: pathName
-
create a new UNIX server socket providing service at a pathname.
If the system does not support unix domain sockets (i.e. VMS or MSDOS),
return nil.
Usage example(s):
|s s2|
'/tmp/foo' asFilename remove.
s := Socket newUNIXserverAt:'/tmp/foo'.
s listenFor:5.
s2 := s accept.
|
obsolete
-
connectTo: service on: host
-
standard & easy client setup:
create new client tcp socket, bind and connect;
return the socket.
The thread blocks (interruptable), until the connection is established.
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
networkLongOrderIsMSB
-
return the well known fact, that network byte order is most significant byte first
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
networkShortOrderIsMSB
-
return the well known fact, that network byte order is most significant byte first
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
provide: aService
-
standard & easy server setup:
create a new TCP server socket providing a service.
** This is an obsolete interface - do not use it (it may vanish in future versions) **
obsolete host queries
-
appletalkAddressOfHost: aHostName
-
return the APPLETALK address for a hostname as a byteArray,
where the network bytes come first (no matter what the local byteorder is)
followed by the node byte.
If the host is unknown, return nil.
This is the reverse operation to #hostWithAppletalkAddress:.
WARNING: untested code - I have no appletalk to test this.
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
hostWithAppletalkAddress: addrByteArray
-
return the hostname for an APPLETALK address.
The address is supposed to be a byteArray consisting of 3 bytes,
the network bytes come first (no matter what the local byteorder is).
The last byte is the node number.
Nil is returned for an unknown host or if it's not an appletalk host.
This is is the reverse operation to #appletalkAddressOfHost:.
WARNING: untested code - I have no appletalk to test this.
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
hostWithIpAddress: addrByteArray
-
return the hostname for an IP (internet-) address.
The address is supposed to be a byteArray consisting of 4 bytes,
Nil is returned for an unknown host or if it's not an internet host.
This is the reverse operation to #ipAddressOfHost:.
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
hostWithIpV6Address: addrByteArray
-
return the hostname for an IPv6 (internet-) address.
The address is supposed to be a byteArray consisting of 16 bytes,
Nil is returned for an unknown host or if it's not an internet host.
This is the reverse operation to #ipV6AddressOfHost:.
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
ipAddressOfHost: aHostName
-
return the IP (internet-) number for a hostname as a byteArray,
where the network bytes come first (no matter what the cpus byteOrder is).
If the host is unknown, return nil.
This is the reverse operation to #hostWithIpAddress:.
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
ipV6AddressOfHost: aHostName
-
return the IPv6 (internet-) number for a hostname as a byteArray,
where the network bytes come first (no matter what the cpus byteOrder is).
If the host is unknown, return nil.
This is the reverse operation to #hostWithIpV6Address:.
** This is an obsolete interface - do not use it (it may vanish in future versions) **
queries
-
nameAndProtocolOfService: aNameOrNumber
-
returns the service name (as string) and protocol for a given port nr
or nil if no such service exists.
Usage example(s):
Socket nameAndProtocolOfService:79 => #('finger' 'tcp')
Socket nameAndProtocolOfService:80 => #('http' 'tcp')
Socket nameAndProtocolOfService:8080 => #('http-alt' 'tcp')
Socket nameAndProtocolOfService:3306 => #('mysql' 'tcp')
Socket nameAndProtocolOfService:33060 => #('mysqlx' 'tcp')
Socket nameAndProtocolOfService:1900 => #('ssdp' 'tcp')
|
-
nameOfService: aNameOrNumber
-
returns the service name (as string) for a given port nr
or nil if no such service exists.
Usage example(s):
Socket nameOfService:79
Socket nameOfService:80
Socket nameOfService:8080
|
-
namesAndProtocolsOfService: aNameOrNumber
-
returns a collection of service names (as string), service protocol (string)
and service port,
given a port nr or service name
or an empty collection if no such service exists.
Returns something like #(#('ping' 'udp' portNr) ('ping' 'tcp' portNr)))
Usage example(s):
Socket namesAndProtocolsOfService:79
Socket namesAndProtocolsOfService:80
Socket namesAndProtocolsOfService:8080
Socket namesAndProtocolsOfService:33060
Socket namesAndProtocolsOfService:1900
|
-
peerFromDomain: domain name: peerName port: port
-
marked as obsolete by Stefan Vogel at 1-Feb-2024
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
peerNameFromDomain: domain peer: peer
-
marked as obsolete by Stefan Vogel at 1-Feb-2024
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
portOfService: aNameOrNumber
-
returns the port-number for a given IP-service
or nil if no such service exists;
- used to convert service names to portNumbers
Usage example(s):
Socket portOfService:'finger'
Socket portOfService:'nntp'
Socket portOfService:'echo'
Socket portOfService:'snmp'
Socket portOfService:'ssdp'
|
-
portOfService: aNameOrNumber protocol: aProtocol
-
returns the port-number for a given IP-service
or nil if no such service exists;
- used to convert service names to portNumbers
Usage example(s):
Socket portOfService:'echo' protocol:'udp'
Socket portOfService:'echo' protocol:'tcp'
Socket portOfService:'ssdp' protocol:'udp'
Socket portOfService:'ssdp' protocol:'tcp'
|
-
protocolOfService: aNameOrNumber
-
returns the protocol (as string) for a given IP-service
or nil if no such service exists.
Usage example(s):
Socket protocolOfService:'finger'
Socket protocolOfService:'nntp'
Socket protocolOfService:'xxx'
Socket protocolOfService:79
Socket protocolOfService:'snmp'
Socket protocolOfService:'ssdp'
Socket nameAndProtocolOfService:'ssdp'
Socket nameAndProtocolOfService:1900
|
-
socketAddressClassForDomain: domain
-
self socketAddressClassForDomain:#AF_INET
self socketAddressClassForDomain:#AF_UNIX
-
supportedProtocolFamilies
-
return a collection of supported protocol families.
This list specifies what the Socket class supports -
socket creation may still fail, if your system was built
without it.
Usage example(s):
Socket supportedProtocolFamilies
|
-
typeOfProtocol: aProtocol
-
given a protocols name (i.e. tcp, udp etc) return the connection type.
This method needs more ... - or is there a way to get this from the system ?
Usage example(s):
Socket typeOfProtocol:'tcp'
Socket typeOfProtocol:'ucp'
Socket typeOfProtocol:(Socket protocolOfService:'nntp')
Socket typeOfProtocol:(Socket protocolOfService:'echo')
|
-
wellknownNameAndProtocolOfService: aNumber
-
returns the service name (as string) and protocol for a given port nr
or nil if unknown.
This is a fallback, for some heuristic wellknown services
(for which getservbyport does not return anything useful)
Compatibility-Dolphin
-
setReceiveTimeout: milliseconds
-
-
setSendTimeout: milliseconds
-
Compatibility-ST80
-
acceptNonBlock
-
-
ioConnection
-
-
notReadySignal
-
ST-80 mimicry.
for now - this is not yet raised
-
readAppendStream
-
ST-80 mimicry.
In ST-80, socket is not a stream, but refers to one.
ST-80 code therefore uses 'Socket readWriteStream' to access
the actual stream.
In ST/X, sockets inherit from stream, so
this method returns the receiver, for transparency
-
readStream
-
ST-80 mimicry.
In ST-80, socket is not a stream, but refers to one.
ST-80 code therefore uses 'Socket readStream' to access
the actual stream.
In ST/X, sockets inherit from stream, so
this method returns the receiver, for transparency
-
writeStream
-
ST-80 mimicry.
In ST-80, socket is not a stream, but refers to one.
ST-80 code therefore uses 'Socket writeStream' to access
the actual stream.
In ST/X, sockets inherit from stream, so
this method returns the receiver, for transparency
Compatibility-Squeak
-
address
-
-
bindTo: interfaceAddr port: portNr
( an extension from the stx:libcompat package )
-
-
connectToHostNamed: hostName port: portNr
-
-
dataAvailable
-
-
destroy
-
-
listenOn: aPortNr
-
-
listenOn: aPortNr backlogSize: aNumber
-
-
localAddress
( an extension from the stx:libcompat package )
-
^ self address
-
localPort
-
-
noTimeout
-
disable timeouts - dummy for now
-
peerName
-
return my peer as SocketAddress (i.e. ipAddr + port)
(bad naming: not as string) ;
May return nil if not yet setup completely.
-
primSocketLocalPort: aSocket
( an extension from the stx:libcompat package )
-
-
receiveDataInto: aDataBuffer
-
receive data
Return the number of bytes received.
The thread blocks until data arrives - you may want to wait before
receiving, using #readWait or #readWaitWithTimeout:.
-
receiveUDPDataInto: aDataBuffer
( an extension from the stx:libcompat package )
-
in squeak, an UDP-receive into aDataBuffer returns a 4-element vector consisting of:
number of bytes
host address of sender
portnr of sender
true/false if error
-
sendData: aStringOrByteArray
-
Send all of the data in the given array, even if it requires multiple calls to send it all.
Return the number of bytes sent.
-
sendUDPData: bytes toHost: aHostAddr port: portNr
( an extension from the stx:libcompat package )
-
-
setOption: optionName value: optionValue
( an extension from the stx:libcompat package )
-
Not all OperatingSystems offer this functionality for any option
(returns false, if unsupported)
-
socketHandle
( an extension from the stx:libcompat package )
-
-
waitForAcceptFor: secondsToWait
-
timed out
-
waitForData
( an extension from the stx:libcompat package )
-
-
waitForDataForMsecs: timeout ifClosed: closedBlock ifTimedOut: timedOutBlock
( an extension from the stx:libcompat package )
-
Seconds resolution is way too much for for instance, UDP sockets running on local network, use this when timeouts > 1 sec is desirable
-
waitForDataIfClosed: ifClosedBlock
( an extension from the stx:libcompat package )
-
wait for incoming data;
if the socket gets closed, evaluate aBlock
accepting connections
-
accept
-
create a new TCP socket from accepting on the receiver.
This method will suspend the current process if no connection is waiting.
For ST-80 compatibility
Usage example(s):
|sock newSock|
sock := Socket provide:8004.
sock listenFor:5.
newSock := sock accept.
|
-
blockingAccept
-
create a new TCP socket from accepting on the receiver.
This method will suspend the smalltalk image with all smalltalk processes if no connection is waiting.
For ST-80 compatibility
binding
-
bindAnonymously
-
bind to any address. A free port will be allocated.
Our own socket address will be determined after connection set up.
This is the default after the socket has been created
Usage example(s):
self newTCP bindAnonymously; listenFor:1; yourself
self newTCP bindAnonymously; port
|
-
bindAnonymouslyToAddress: aSocketAddress
-
bind to address addressString.
A free port will be allocated
Usage example(s):
self newTCP bindAnonymouslyToAddress:IPSocketAddress localHost; listenFor:1; yourself
|
-
bindTo: aSocketAddress
-
ST80 compatible bind, expecting a socketAddress argument.
The socketAddress object (an instance of SocketAddress)
is supposed to respond to #portOrName and #address requests.
-
bindTo: portNrOrNameString address: addressString
-
Old interface: bind the socket to an address
- returns true if ok, false otherwise.
Notify with a SocketErrorNotification on error.
The interpretation of hostOrPathNameOrSocketAddrOrNil portNrOrName depends on the domain:
Best use a SocketAddress
For backward compatibility:
AF_INET domain can also use (4byte) byteArray like internet numbers,
AF_UNIX domain cab use pathname strings.
-
bindTo: portNrOrNameOrNil address: hostOrPathNameOrSocketAddrOrNil reuseAddress: reuse
-
Old interface: bind the socket to an address
Notify with a SocketErrorNotification on error.
- returns true if ok, false otherwise.
The interpretation of hostOrPathNameOrSocketAddrOrNil portNrOrName depends on the domain:
Best use a SocketAddress
For backward compatibility:
AF_INET domain can also use (4byte) byteArray like internet numbers,
AF_UNIX domain can use pathname strings.
The reuse boolean argument controls if the SO_REUSEADDR socket option
is to be set (to avoid the 'bind: address in use' error).
Usage example(s):
(Socket domain:#'AF_INET' type:#stream)
bindTo:2144 address:nil; yourself
|
-
bindTo: aSocketAddress reuseAddress: reuse
-
Bind the socket to aSocketAddress - returns true if ok, false otherwise.
Notify with a SocketErrorNotification on error.
The reuse boolean argument controls if the SO_REUSEADDR socket option
is to be set (to avoid the 'bind: address in use' error).
You can bind to nil to bind to anyHost and assign a random port.
Usage example(s):
(Socket domain:#'AF_INET' type:#stream)
bindTo:(IPSocketAddress anyHost port:445) reuseAddress:false;
yourself.
(Socket domain:#'AF_INET' type:#stream)
bindTo:139 reuseAddress:false;
yourself.
(Socket domain:#'AF_INET6' type:#stream)
bindTo:nil reuseAddress:false;
yourself.
(Socket domain:#'AF_INET' type:#stream)
bindTo:(IPSocketAddress localHost port:2122) reuseAddress:false;
yourself.
(Socket domain:#'AF_UNIX' type:#stream)
bindTo:nil reuseAddress:false;
yourself.
|
-
listen
-
start listening; return true if ok, false on error.
Notify with a SocketErrorNotification on error.
One outstanding connect request may be queued on the socket
(i.e. this is the same as listenFor:1)
-
listenFor: aNumber
-
start listening; return true if ok, false on error.
Notify with a SocketErrorNotification on error.
aNumber is the number of connect requests, that may be queued on the socket
Usage example(s):
[
|sock|
sock := Socket newTCP.
sock listenFor:1.
sock
] on:SocketErrorNotification do:[:ex|
ex halt.
].
|
closing
-
abortAndClose
-
immediately abort the connection:
discard buffered data and close the stream
-
shutDown
-
shutDown (initiate a graceful close)
and close (free the filedescriptor) the socket.
The close will return immediately and buffered data will be sent in the
background, unless you set linger > 0
-
shutDownInput
-
shutDown the input side of the socket.
After already received data that hat been buffered in the OS,
any read on the socket will signal end-of-file from now on.
The other side MAY be informed, that no more data will be accepted
(e.g. setting the TCP-Windowsize to 0)
-
shutDownOutput
-
shutDown the output side of the socket.
Any write to the socket will signal end-of-file from now on.
An orderly release (TCP FIN) will be initiated after the last buffered data
has been sent, so the other side will get a end-of-file condition eventually.
If you set linger > 0, the operation will wait until buffered data
has been delivered to the peer.
Otherwise the operation returns immediately.
connecting
-
connectTo: aSocketAddress
-
-
connectTo: hostOrPathName port: portNrOrName
-
Backward compatibility connect; connect to port, portNrOrNameOrNil on host, hostOrPathNameOrSocketAddr.
For backward compatibility, hostOrPathNameOrSocketAddr may be also a string or a byteArray,
but it is recommended to pass SocketAddress instances.
Return true if ok, false otherwise.
The current process will block (but not the whole Smalltalk) until the connection is established.
See also: #connectTo:port:withTimeout: for a somewhat nicer interface.
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
connectTo: hostOrPathNameOrSocketAddr port: portNrOrNameOrNil withTimeout: milliSecondsOrTimeDuration
-
Backward compatibility connect; connect to port, portNrOrNameOrNil on host, hostOrPathNameOrSocketAddr.
For backward compatibility, hostOrPathNameOrSocketAddr may be also a string or a byteArray,
but it is recommended to pass SocketAddress instances.
Callers should be changed to call connectTo:aSocketAddress withTimeout:
(i.e. pass a socketAddress)
Return true if ok, false otherwise.
Notify with a SocketErrorNotification on error.
The current process will block (but not the whole Smalltalk) until the connection is established,
or milliSecondsOrTimeDuration milliseconds have passed.
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
connectTo: aSocketAddress withTimeout: milliSecondsOrTimeDuration
-
Connect to a SocketAddress.
Return true if ok, false otherwise.
Notify with a SocketErrorNotification on error.
The current process will block (but not the whole Smalltalk) until the connection is established,
or timeout milliseconds have passed.
datagram transmission
-
receiveBuffer: aDataBuffer start: startIndex for: nBytes
-
receive data
Return the number of bytes received.
The thread blocks until data arrives - you may want to wait before
receiving, using #readWait or #readWaitWithTimeout:.
-
receiveFrom: aSocketAddress buffer: aDataBuffer
-
receive datagramm data - put address of originating host into
aSocketAddress, data into aDataBuffer.
aDataBuffer must be ByteArray-like.
For backward compatibility, aSocketAddress may be a non-SocketAddress;
then, it must be a byteArray with appropriate size for the addressBytes.
Return the number of bytes received.
The thread blocks until data arrives - you may want to wait before
receiving, using #readWait or #readWaitWithTimeout:.
-
receiveFrom: aSocketAddress buffer: aDataBuffer start: startIndex for: nBytes
-
Modified (format): / 21-03-2018 / 19:32:27 / stefan
-
receiveFrom: aSocketAddress buffer: aDataBuffer start: startIndex for: nBytes flags: flags
-
receive datagramm data
- put address of originating host into aSocketAddress, data into aDataBuffer.
aDataBuffer must be ByteArray-like.
For backward compatibility, aSocketAddress may be a non-SocketAddress;
then, it must be a byteArray with appropriate size for the addressBytes.
Return the number of bytes received.
The thread blocks until data arrives - you may want to wait before
receiving, using #readWait or #readWaitWithTimeout:.
-
sendBuffer: aDataBuffer start: startIndex for: nBytes flags: flags
-
send data. aDataBuffer be ByteArray-like.
Return the number of bytes transmitted, or a negative number on error.
-
sendTo: aSocketAddress buffer: buffer
-
send datagramm data - fetch address of destination host from
aSocketAddress, data from aDataBuffer.
aDataBuffer must be ByteArray-like.
aSocketAddress must be a valid SocketAddress for my domain
(i.e. for IPv4, an IPSocketAddress).
For backward compatibility, a ByteArray is still supported in aSocketAddress
(i.e. for IPv4, a 4-byte byteArray).
Return the number of bytes transmitted.
-
sendTo: aSocketAddress buffer: buffer start: startIndex for: count
-
send datagramm data - fetch address of destination host from
aSocketAddress, data from aDataBuffer.
aDataBuffer must be ByteArray-like.
aSocketAddress must be a valid SocketAddress for my domain
(i.e. for IPv4, an IPSocketAddress).
For backward compatibility, a ByteArray is still supported in aSocketAddress
(i.e. for IPv4, a 4-byte byteArray).
Return the number of bytes transmitted.
-
sendTo: aSocketAddress buffer: aDataBuffer start: startIndex for: nBytes flags: flags
-
send datagramm data - fetch address of destination host from
aSocketAddress, data from aDataBuffer starting at startIndex,
sending count bytes.
aDataBuffer must be ByteArray-like.
aSocketAddress must be a valid SocketAddress for my domain
(i.e. for IPv4, an IPSocketAddress).
For backward compatibility, a ByteArray is still supported in aSocketAddress
(i.e. for IPv4, a 4-byte byteArray).
Return the number of bytes transmitted.
error reporting
-
reportError: osErrorNumber
-
report an error to the initiator of a Socket operation.
We raise a notification for newer code, and also
return false for old code not catching the notification.
finalization
-
finalize
-
do an abortive release - discard buffered data
initialization
-
initialize
-
transparent
low level
-
getSocketAdress
-
BAD SPELLING, of #getSocketAddress, kept for compatibility with swazoo
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
getSocketError
-
get the SO_ERROR form the socket, which indicates the
result of an asynchronous operation
-
listenWithBacklog: aNumber
-
same as listenFor: - backward compatibility with old ST/X
** This is an obsolete interface - do not use it (it may vanish in future versions) **
-
primAcceptOn: aServerSocket blocking: blocking
-
accept a connection on a server port (created with:'Socket>>newTCP:')
usage is: (Socket basicNew acceptOn:(Socket newTCP:9999)).
Return the true if ok; false if not.
Notify with a SocketErrorNotification on error.
If blocking is true, the accept() syscall (and the whole smalltalk image)
will block, until a connection is accepted.
If blocking is false, this call will return immediately, if there is no connection pending.
-
setKeepAlive: aBoolean
-
set/clear the SO_KEEPALIVE socket option
-
setSocketOption: option argument: arg1 argument: arg2
-
option is a symbol:
#IP_DROP_MEMBERSHIP <addr-bytes> <addr-bytes>
#IP_ADD_MEMBERSHIP <addr-bytes> <addr-bytes>
#IP_TTL <int>
#IP_MULTICAST_TTL <int>
#IPV6_V6ONLY <bool>
#SO_BROADCAST <bool>
#SO_CONDITIONAL <bool>
#SO_DEBUG <bool>
#SO_DONTLINGER <bool>
#SO_LINGER <bool> <nil | int>
#SO_DONTROUTE <bool>
#SO_KEEPALIVE <bool>
#SO_OOBINLINE <bool>
#SO_RCVBUF <int>
#SO_SNDBUF <int>
#SO_REUSEADDR <bool>
#SO_REUSEPORT <bool>
#SO_EXCLUSIVEADDRUSE <bool>
#SO_RCVTIMEO <seconds-int> <uSec-int>
#SO_SNDTIMEO <seconds-int> <uSec-int>
#TCP_NODELAY <bool>
arg is option specific
#OPTION { <level-int> <option-int> } <rawData>
to generate an arbitrary socket opton call, in case it is as-yet unimplemented
Must generate a matching byteArray as rawData
and pass both level and option as 2-element array in first arg
-
shutdown: howNum
-
shutDown the socket - inform it that no more I/O will be performed.
0 - read side (no further reads)
Stop receiving data for this socket. If further data arrives, reject it
(the tcp receive window is closed, so the peer cannot send more data).
Data that has already been received and buffered in the OS can still be read.
1 - write side (no further writes - subsequent writes will fail)
first, all queued data will be delivered to the peer.
Then, an orderly release (TCP FIN) is sent to signal the peer,
that we will not send more data.
2 - both read side and write side.
The connection is terminated, but the file descriptor still needs to be closed.
printing & storing
-
name
-
for monitoring (see ExternalStreamMonitor)
-
name: aString
-
for monitoring (see ExternalStreamMonitor)
-
printOn: aStream
-
(comment from inherited method)
append a user printed representation of the receiver to aStream.
The format is suitable for a human - not meant to be read back.
queries
-
canAcceptWithoutBlocking
-
return true, if an incoming connections is pending (i.e.
an accept operation will not block the smalltalk process), false otherwise.
We know, that error conditions do not block, so return true for errors.
-
domain
-
return the sockets addressing domain (i.e. #AF_INET, #AF_INET6, #AF_UNIX, ...)
-
getFullPeerAddress
-
Answer the peer socket address; that is the socket address of the
partner's host after an connect or accept.
-
getFullSocketAddress
-
Answer my own address (I am bound to this address).
Note that this address may change after a connect or accept.
-
getName
-
return the name; here, we return the ports name
-
getPeer
-
ST-80 compatibility: return an IPSocketAddress instance representing
my hostname/port combination.
If you are interested in the hostname, use getPeerName directly.
-
getPeerName
-
return the peer name; that's the hostname (or dotted name) of the
partner's host after an accept.
-
getSocketAddress
-
answer my own address (I am bound to this address).
Note that this address may change after connect or accept.
-
isActive
-
return true, if the receiver has a connection or is bound or listening
-
isConnected
-
return true, if the receiver has a connection
-
isListening
-
-
port
-
return the port number (or name for unix-sockets) to which the socket is bound
- so this is the local port.
Usage example(s):
port := self getFullSocketAddress port.
|
-
socketAddressClass
-
get the matching SocketAddress class for this socket's domain
-
type
-
return the sockets connection type (i.e. #datagram, #stream etc)
socket setup
-
domain: domainArg type: typeArg
-
set up socket with domain and type.
This is a low level entry; no binding, listening or connect
is done. Both arguments must be symbols from one of
#AF_INET, #AF_INET6, #AF_UNIX ... and #stream, #datagram, #raw resp.
-
domain: domainArg type: typeArg protocol: protocolNumber
-
set up socket with domain, type and protocol number.
This is a low level entry; no binding, listening or connect
is done. Both arguments must be symbols from one of
#AF_INET, #AF_INET6, #AF_UNIX ... and #stream, #datagram, #raw resp.
Usage example(s):
Socket new domain:#AF_INET type:#stream
Socket new domain:#AF_UNIX type:#stream
|
specials
-
linger: anIntegerOrNil
-
set the linger behavior on close:
anIntegerOrNil == nil: close returns immediately, socket tries
to send buffered data in background.
anIntegerOrNil == 0: close returns immediately, bufferd data is discarded.
anIntegerOrNil > 0: close waits this many seconds for buffered data
to be delivered, after this time buffered data is
discarded and close returns with an error.
(returns false, if unsupported)
-
receiveBufferSize
-
get the send buffer size - for special applications only.
Not all operatingSystems offer this functionality
(returns nil, if unsupported)
-
receiveBufferSize: size
-
set the receive buffer size - for special applications only.
Not all operatingSystems offer this functionality
(returns false, if unsupported)
-
receiveTimeout
-
get the receive timeout in millis - for special applications only.
Not all operatingSystems offer this functionality
(returns nil, if unsupported)
Usage example(s):
Socket newTCP receiveTimeout
|
-
receiveTimeout: secondsOrTimeDuration
-
set the receive timeout - for special applications only.
Not all operatingSystems offer this functionality
(returns false, if unsupported).
From linux manpage:
SO_RCVTIMEO and SO_SNDTIMEO
Specify the receiving or sending timeouts until reporting an error. The argument is a
struct timeval. If an input or output function blocks for this period of time, and data has
been sent or received, the return value of that function will be the amount of data trans-
ferred; if no data has been transferred and the timeout has been reached, then -1 is
returned with errno set to EAGAIN or EWOULDBLOCK, or EINPROGRESS (for connect(2)) just as if
the socket was specified to be nonblocking. If the timeout is set to zero (the default),
then the operation will never timeout. Timeouts only have effect for system calls that per-
form socket I/O (e.g., read(2), recvmsg(2), send(2), sendmsg(2)); timeouts have no effect
for select(2), poll(2), epoll_wait(2), and so on.
Usage example(s):
Socket newTCP
receiveTimeout:5s;
receiveTimeout
|
-
sendBufferSize
-
get the send buffer size - for special applications only.
Not all operatingSystems offer this functionality
(returns nil, if unsupported)
-
sendBufferSize: size
-
set the send buffer size - for special applications only.
Not all operatingSystems offer this functionality
(returns false, if unsupported)
-
sendTimeout
-
get the send timeout in millis - for special applications only.
Not all operatingSystems offer this functionality
(returns nil, if unsupported)
Usage example(s):
Socket newTCP sendTimeout
|
-
sendTimeout: secondsOrTimeDuration
-
set the send timeout - for special applications only.
Not all operatingSystems offer this functionality
(returns false, if unsupported).
From linux manpage:
SO_RCVTIMEO and SO_SNDTIMEO
Specify the receiving or sending timeouts until reporting an error. The argument is a
struct timeval. If an input or output function blocks for this period of time, and data has
been sent or received, the return value of that function will be the amount of data trans-
ferred; if no data has been transferred and the timeout has been reached, then -1 is
returned with errno set to EAGAIN or EWOULDBLOCK, or EINPROGRESS (for connect(2)) just as if
the socket was specified to be nonblocking. If the timeout is set to zero (the default),
then the operation will never timeout. Timeouts only have effect for system calls that per-
form socket I/O (e.g., read(2), recvmsg(2), send(2), sendmsg(2)); timeouts have no effect
for select(2), poll(2), epoll_wait(2), and so on.
Usage example(s):
Socket newTCP
sendTimeout:5s;
sendTimeout
|
-
setTCPCork: aBoolean
-
enable/disable TCP_CORK (do-not-send-partial-frames)
For special applications only.
Not all OperatingSystems offer this functionality
(returns false, if unsupported)
-
setTCPNoDelay: aBoolean
-
enable/disable TCP_NODELAY (i.e. disable/enable the Nagle algorithm)
For special applications only.
Not all OperatingSystems offer this functionality
(returns false, if unsupported)
support websocket
-
blockingNextPutAllForNonBlockingSocket: someBytes
-
explanation of the method name:
blocking -> this method blocks its STX process until all bytes have been written
ForNonBlockingSocket -> this method only works with non-blocking sockets
the write is done within the current thread,
but the primitiv #send returns because the socket is non-blocking (in case of would block).
of cause if you write big data at once and the socket never would block, STX will freeze,
so please split big data into small packages
-
setNonBlocking
-
DO NOT move this functionality into Win32OperatingSystem #setBlocking:fd:,
because it will not work correctly, caused by the following problems.
and even if the problems has been fixed, it would change the behavior for all sockets (not only websockets)
-
systemBlockingNextPutAll: bytes
-
explanation of the method name:
systemBlocking -> this method blocks the entire STX
until all bytes have been written or until the socket would block
so please split big data into small packages
testing
-
isSSLSocket
-
waiting
-
waitForConnectOrAccept: secondsOrTimeDurationOrNil
-
wait for the connection secondsOrTimeDurationOrNil.
Return true when connect finished or an incoming connection is
pending for accept.
Return false on timeout.
-
waitForConnection: secondsOrTimeDurationOrNil
-
wait for the connection secondsOrTimeDurationOrNil.
Return true if connected
-
waitForConnectionUntil: deadlineTimestamp
-
Wait up until the given deadline for a connection to be established.
Return true if it is established by the deadline, false if not.
-
waitForConnectionWithErrorOnTimeout: secondsOrTimeDurationOrNil
-
wait for the connection secondsOrTimeDurationOrNil.
Raise an error if not connected.
-
waitForNewConnectionOrDataOnAny: otherConnections timeout: secondsOrTimeDurationOrNil
-
suspend the current process, until either a new connection comes
in at the receiver (a listening socket), or data arrives on any of the otherConnections.
For a new connection, an accept is performed and the new socket is returned.
For an old connection, that socket is returned.
In any case, the caller gets a socket to operate on as return value,
or nil, if a timeout occurred.
This method implements the inner wait-primitive of a multi-connection
server application.
-
waitForNewConnectionWithTimeout: secondsOrTimeDurationOrNil
-
suspend the current process, until a new connection comes
in at the listening receiver or a timeout occurs.
For a new connection, an accept is performed and the new socket is returned.
Returns nil, if a timeout occurred.
This method implements the inner wait-primitive of a single-connection
server application.
example (get help info from an nntp server):
|sock|
sock := Socket newTCPclientToHost:'smtp.exept.de' port:'smtp'.
sock isNil ifTrue:[
self warn:'no smtp daemon is running'.
^ self
].
Transcript showCR:sock nextLine.
sock nextPutAll:'HELO STX socket test'; cr.
Transcript showCR:sock nextLine.
sock close
|
example (connect to finger daemon, get users entry):
|sock entry|
sock := Socket newTCPclientToHost:'localhost' port:'finger'.
sock isNil ifTrue:[
self warn:'no finger daemon is running'.
^ self
].
sock useCRLF:true.
sock buffered:false.
sock isNil ifTrue:[
Transcript showCR:'cannot connect to local finger daemon'
] ifFalse:[
sock nextPutAll:(OperatingSystem getLoginName).
sock cr.
entry := sock nextLine.
Transcript showCR:entry.
sock close
]
|
example (connect to an ftp server):
|sock|
sock := Socket newTCPclientToHost:'www.exept.de' port:'ftp'.
sock buffered:false.
Transcript showCR:sock nextLine.
sock nextPutAll:('USER ' , 'anonymous'); cr.
Transcript showCR:sock nextLine.
sock nextPutAll:('PASS ' , 'fooBar'); cr.
Transcript showCR:sock nextLine.
sock nextPutAll:'HELP'; cr.
[
|line|
line := sock nextLine.
Transcript showCR:line.
(line at:4) = $-
] whileTrue.
sock close.
'don't know enough of the ftp protocol to continue here ...'
|
example (connect to an snmp server [UDP]):
Note: this is not a real connection, only the destination address is
being fixed.
|sock port|
sock := Socket newUDP.
port := Socket portOfService:'snmp'.
sock connectTo:'224.1.2.3' port:port.
sock buffered:false.
Transcript showCR:'got it'.
sock close.
|
example (await connection from a client and read some data):
|connectSock sock|
connectSock := Socket newTCPserverAtPort:9998.
connectSock isNil ifTrue:[
Transcript showCR:'socket setup failed.'.
] ifFalse:[
Transcript showCR:'listen ..'.
(connectSock listenFor:5) ifFalse:[
Transcript showCR:'listen failed.'.
] ifTrue:[
Transcript showCR:'wait'.
connectSock readWait.
Transcript showCR:'accept'.
sock := connectSock accept.
sock isNil ifTrue:[
Transcript showCR:'accept failed.'.
] ifFalse:[
sock buffered:false.
Transcript showCR:'server: got it'.
'can now do transfer via sock'.
Transcript showCR:'read'.
Transcript showCR:('got: ' , sock nextLine).
Transcript showCR:'close'.
sock close
].
connectSock close.
]
]
|
example (connect to above server and send some data):
|sock|
sock := Socket newTCPclientToHost:'localhost' port:9998.
sock isNil ifTrue:[
Transcript showCR:'nope'
] ifFalse:[
sock buffered:false.
Transcript showCR:'client: got it'.
'can now do transfer via sock'.
Transcript showCR:'sending <hello>'.
sock nextPutLine:'hello'.
sock close
]
|
example: UNIX domain socket (await connection from a client and read some data):
|connectSock sock|
'/tmp/ud_socket' asFilename remove.
connectSock := Socket newUNIXserverAt:'/tmp/ud_socket'.
connectSock isNil ifTrue:[
Transcript showCR:'socket setup failed.'.
] ifFalse:[
Transcript showCR:'listen ..'.
(connectSock listenFor:5) ifFalse:[
Transcript showCR:'listen failed.'.
] ifTrue:[
Transcript showCR:'wait'.
connectSock buffered:false.
connectSock readWait.
Transcript showCR:'accept'.
sock := connectSock accept.
sock isNil ifTrue:[
Transcript showCR:'accept failed.'.
] ifFalse:[
sock buffered:false.
Transcript showCR:'server: got it'.
'can now do transfer via sock'.
Transcript showCR:'read'.
Transcript showCR:('got: ' , sock nextLine).
Transcript showCR:'close'.
sock close
].
connectSock close.
]
]
example (connect to above server and send some data;
Notice, this fails, if above server code is executed in the same ST/X image
(at least on LINUX), since the OS does not correctly handle
a connect from within an interrupted accept system call
On SGI's SVR4, this works ok
|sock|
sock := Socket newUNIXclientTo:'/tmp/ud_socket'.
sock isNil ifTrue:[
Transcript showCR:'nope'
] ifFalse:[
sock buffered:false.
Transcript showCR:'client: got it'.
'can now do transfer via sock'.
Transcript showCR:'sending <hello>'.
sock nextPutLine:'hello'.
sock close
]
|
example (UDP await packet from a client and read some data):
|udpSock sock addr n dataBuffer|
udpSock := Socket newUDPserverAtPort:9999.
udpSock isNil ifTrue:[
Transcript showCR:'socket setup failed.'.
] ifFalse:[
Transcript showCR:'wait'.
udpSock readWait.
addr := IPSocketAddress new.
dataBuffer := ByteArray new:1000.
n := udpSock receiveFrom:addr buffer:dataBuffer start:1 for:dataBuffer size.
n > 0 ifTrue:[
Transcript showCR:('got: ' , n printString , 'bytes from ' , addr printString).
Transcript showCR:('data: ' , (dataBuffer copyTo:n) printString).
] ifFalse:[
Transcript showCR:'read failed'.
].
Transcript showCR:'close'.
udpSock close
]
|
example (connect to above UDP server and send some data;
|sock|
sock := Socket newUDP.
sock isNil ifTrue:[
Transcript showCR:'nope'
] ifFalse:[
sock
sendTo:(IPSocketAddress hostName:'127.0.0.1' port:9999) buffer:'hello world'.
sock close
]
|
example (UDP await packet from a client and read some multicast data - here SSDP data):
|udpSock sock addr n dataBuffer|
udpSock := Socket newUDPserverAtPort:1900.
udpSock isNil ifTrue:[
Transcript showCR:'socket setup failed.'.
] ifFalse:[
(udpSock setSocketOption:#'IP_ADD_MEMBERSHIP' argument:#[239 255 255 250] argument:#[0 0 0 0]) ifFalse:[
Transcript showCR:'IP_ADD_MEMBERSHIP0 failed.'.
].
(udpSock setSocketOption:#'IP_ADD_MEMBERSHIP' argument:#[239 255 255 250] argument:#[127 0 0 1]) ifFalse:[
Transcript showCR:'IP_ADD_MEMBERSHIP1 failed.'.
].
(udpSock setSocketOption:#'IP_ADD_MEMBERSHIP' argument:#[239 255 255 250] argument:#[172 23 1 62]) ifFalse:[
Transcript showCR:'IP_ADD_MEMBERSHIP2 failed.'.
].
[
[
Transcript showCR:'wait'.
udpSock readWait.
addr := IPv6SocketAddress new.
dataBuffer := ByteArray new:1000.
n := udpSock receiveFrom:addr buffer:dataBuffer start:1 for:dataBuffer size.
n > 0 ifTrue:[
Transcript showCR:('got: ' , n printString , 'bytes from ' , addr asIPv4SocketAddressIfPossible printString).
Transcript showCR:('data: ' , (dataBuffer copyTo:n) printString).
] ifFalse:[
Transcript showCR:'read failed'.
].
] loop.
] ensure:[
Transcript showCR:'close'.
udpSock close.
].
]
|
example (connect to above UDP server and send some multicast data):
|sock|
sock := Socket newUDP.
sock isNil ifTrue:[
Transcript showCR:'nope'
] ifFalse:[
sock setSocketOption:#'IP_MULTICAST_TTL' argument:4 argument:nil.
[
[
sock sendTo:(IPSocketAddress hostName:'239.255.255.250' port:1900) buffer:'Invalid SSDP data for test'.
Delay waitForSeconds:2.
] loop.
] ensure:[
sock close.
].
]
|
example: pingWalk (try to ping hosts on the local network)
Note: it dosen't use ICMP ping, but tries to reache the echo service,
which is disabled on most OS.
|myAddress list top hosts walkProcess port|
myAddress := OperatingSystem getNetworkAddresses
keysAndValuesSelect:[:eachIFName :eachAddress|
eachAddress isLocal not
and:[eachIFName = 'wlan0']
].
myAddress := myAddress first hostAddress.
port := Socket portOfService:'echo'.
port isNil ifTrue:[
self error:'dont know echo port'.
^ self
].
top := StandardSystemView new.
top label:'PING net walk'.
list := ScrollableView for:ListView in:top.
list origin:0.0@0.0 corner:1.0@1.0.
top openAndWaitUntilVisible.
walkProcess := [
|l low hi direction tryHostID dottedName hostName conn addr|
l := SortedCollection new.
' only works with type C-net
the code below could simply do 1 to:254 do:[:hostID }
but, to probe likely hosts earlier, the probing is done
ping-pong like around my ip-address (assuming, that other machines
have numbers around my own)'.
low := hi := (myAddress at:4).
direction := 1.
[low > 0 or:[hi < 255]] whileTrue:[
direction > 0 ifTrue:[
hi := hi + 1.
tryHostID := hi.
direction := -1.
] ifFalse:[
low := low - 1.
tryHostID := low.
direction := 1.
].
(tryHostID between:1 and:254) ifTrue:[
dottedName := (myAddress at:1) printString
, '.' , (myAddress at:2) printString
, '.' , (myAddress at:3) printString
, '.' , tryHostID printString.
top label:'PING net walk - trying ' , dottedName.
top windowGroup withCursor:Cursor wait do:[
conn := Socket newTCPclientToHost:dottedName port:port withTimeout:1000.
conn notNil ifTrue:[
addr := Socket ipAddressOfHost:dottedName.
hostName := Socket hostWithIpAddress:addr.
hostName isNil ifTrue:[
hostName :='?'
].
l add:(dottedName paddedTo:15 with:Character space)
, ' '
, (hostName paddedTo:15 with:Character space)
, ' up & reachable'.
list list:l.
conn close.
]
].
].
].
top label:'PING reachable hosts'.
] forkAt:(Processor userBackgroundPriority).
walkProcess name:'ping net walker'.
|
This example creates a simple UDP server that accepts
single packets from anybody and broadcasts them to all
clients that have connected so far.
| socket address buffer msgSize clients |
clients := Set new.
address := IPSocketAddress new.
buffer := String new: 1024.
socket := self newUDPserverAtPort: 6666.
Transcript showCR: 'server starting'.
[
[true] whileTrue: [
(socket readWaitWithTimeoutMs: 200) ifFalse: [
msgSize := socket
receiveFrom: address
buffer: buffer
start: 1
for: buffer size.
clients add: address copy.
clients do: [ :clientAddress |
socket
sendTo: clientAddress
buffer: buffer
start: 1
for: msgSize]]
]
] ensure:[
Transcript showCR: 'server shutting down'.
socket close
]
|
send a datagram to above server:
| socket address buffer host msg |
host := Dialog
request: 'What is the name of the server''s host?'
initialAnswer: 'localhost'.
socket := self newUDP.
address := IPSocketAddress hostName: host port: 6666.
buffer := ByteArray new: 1000.
[
[(msg := Dialog request: 'Say something') isEmpty] whileFalse:[
| replySize stream |
socket writeWait.
stream := buffer writeStream.
stream nextPutAll: msg.
socket sendTo:address buffer:buffer start:1 for:stream position.
socket readWait.
replySize := socket receiveFrom:address buffer:buffer.
replySize > 0 ifTrue: [
Transcript cr; nextPutAll: 'Server acknowledged: '.
Transcript show: ((buffer copyFrom: 1 to: replySize) asString)
]
]
] ensure: [socket close].
Transcript cr
|
loopBack:
|readerTask readingSocket writingSocket|
readingSocket := self newTCPserverAtPort:9999.
readerTask :=
[
|connection|
readingSocket listenFor:1.
connection := readingSocket accept.
readingSocket close.
[connection atEnd] whileFalse:[
Transcript showCR:(connection nextLine).
].
connection close.
] fork.
Delay waitForSeconds:1.
writingSocket := self newTCPclientToHost:'localhost' port:9999.
writingSocket nextPutLine:'Hello'.
writingSocket nextPutLine:'World'.
writingSocket close.
|
This example creates a simple UDP server that accepts
single NTP packets and prints the time on the Transcript.
| socket address buffer msgSize msg |
address := IPSocketAddress new.
buffer := ByteArray new: 1024.
socket := self newUDPserverAtPort:123.
Transcript showCR: 'ntp receiver starting'.
[
[true] whileTrue: [
(socket readWaitWithTimeoutMs:1000) ifFalse:[
msgSize := socket
receiveFrom: address
buffer: buffer
start: 1
for: buffer size.
Transcript showCR: e'got {msgSize} bytes'.
msg := buffer copyTo:msgSize.
]
]
] ensure:[
Transcript showCR: 'server shutting down'.
socket close
]
|
|