class io.Socket
Overview
This class provides high-level asynchronous interface for accessing all kinds of sockets. More…
import "io_base.jncx" import "io_Socket.jnc" class Socket { // fields io.SocketEvents readonly volatile m_activeEvents; std.Error const* readonly volatile m_ioError; bool readonly m_isOpen; // properties io.SocketAddress const property m_address; io.SocketAddress const property m_peerAddress; uint_t autoget property m_readParallelism; size_t autoget property m_readBlockSize; size_t autoget property m_readBufferSize; size_t autoget property m_writeBufferSize; io.SocketOptions autoget property m_options; uintptr_t const property m_osHandle; // construction construct(); destruct(); // methods bool errorcode open( io.AddressFamily family, io.Protocol protocol ); bool errorcode open( io.Protocol protocol, io.SocketAddress const* address ); bool errorcode open(io.Protocol protocol); void close(); bool errorcode connect(io.SocketAddress const* address); bool errorcode listen(size_t backlog = 0); io.Socket* errorcode accept( io.SocketAddress* address = null, bool isSuspended = false ); void unsuspend(); size_t errorcode read( void* p, size_t size ); size_t errorcode write( void const* p, size_t size ); size_t errorcode readDatagram( void* p, size_t size, io.SocketAddress* address ); size_t errorcode writeDatagram( void const* p, size_t size, io.SocketAddress const* address ); long errorcode wait( io.SocketEvents eventMask, void function* handler(io.SocketEvents triggeredEvents) ); bool errorcode cancelWait(long handle); io.SocketEvents blockingWait( io.SocketEvents eventMask, uint_t timeout = -1 ); io.SocketEvents async asyncWait(io.SocketEvents eventMask); // aliases alias dispose = close; };
Detailed Documentation
This class provides high-level asynchronous interface for accessing all kinds of sockets.
Sockets represent endpoints of network communications. Sockets are subdivided into two large subclassess: datagram-oriented and connection-oriented. Furthermore, connection-riented sockets can operate in one of the two modes: client and server. And even though these interfaces don’t share that many commonalities, it so historically happened that they are usually blended into a single socket API.
Jancy follows this traditional approach.
Sample code(client connection-oriented TCP socket):
class MyDialog { // ... io.Socket m_socket; uint_t m_syncId; void connect(string_t addrString); void close(); void waitSocketEvents(); void onWriteButtonClicked(); void onSocketEvent( uint_t syncId, io.SocketEvents triggeredEvents ); } MyDialog.connect(string_t addrString) { io.SocketAddress sockAddr; sockAddr.parse(addrString); m_socket.open(io.Protocol.Tcp); m_socket.connect(sockAddr); waitSocketEvents(); catch: // handle the error... } MyDialog.close() { m_socket.close(); m_syncId++; // events past this point will be discarded as 'late' } MyDialog.waitSocketEvent() { io.SocketEvents eventMask = io.SocketEvents.IoError | io.SocketEvents.IncomingData; if (!(m_socket.m_activeEvents & io.SocketEvents.TcpConnected)) eventMask |= io.SocketEvents.TcpConnected; m_socket.wait(eventMask, onSocketEvent ~(++m_syncId) @ g_mainThreadScheduler); } MyDialog.onWriteButtonClicked() { static char data[] = "a quick brown fox jumps over the lazy dog"; m_socket.write(data, sizeof(data)); } MyDialog.onSocketEvent( uint_t syncId, io.SocketEvents triggeredEvents ) { if (syncId != m_syncId) // late event return; if (triggeredEvents & io.SocketEvents.IoError) { string_t errorString = m_socket.m_ioError.m_description; // ... } if (triggeredEvents & io.SocketEvents.TcpConnected) { // TCP connection established } if (triggeredEvents & io.SocketEvents.IncomingData) { char buffer[256]; size_t size = m_socket.read(buffer, sizeof(buffer)); // ... } waitSocketEvents(); // restart wait }
See also:
io.SocketEvents
, io.SocketAddress
Fields
bool readonly m_isOpen
Holds the open status for the socket, i.e. true
if opened; false
otherwise.
Properties
io.SocketAddress const property m_address
This property is used for getting the local address assigned to this socket. If the address has not been assigned yet, returns empty address.
io.SocketAddress const property m_peerAddress
This property is used for getting the remote address of the peer this socket is connected to. If the connection has not been established yet, returns empty address.
Methods
bool errorcode open( io.AddressFamily family, io.Protocol protocol )
Opens a new unbound socket.
The function accepts three arguments. The first one, family
,
specifies the address family of the new socket(IP4
vs IP6
). The
second argument, protocol
, specifies the protocol of the new socket
(datagram-oriented UDP
vs connection-oriented TCP
). The third
and final argument, flags
can be used to specify additional open
options.
Returns true
on success. If a new socket could not be opened, IO
error supplied by operating system is set and then the function returns
false
[1].
bool errorcode open( io.Protocol protocol, io.SocketAddress const* address )
Opens a new socket and binds it to the specified local address.
The function accepts three arguments. The first one, protocol
,
specifies the protocol of the new socket(datagram-oriented UDP
vs connection-oriented TCP
). The second argument, address
,
specifies the local address to bind the new socket to. The third and
final argument, flags
can be used to specify additional open
options.
Returns true
on success. If a new socket could not be opened, IO
error supplied by operating system is set and then the function returns
false
[1].
bool errorcode open(io.Protocol protocol)
Opens a new unbound socket.
The function is equivalent to the very first overload of open
method
with family
argument set to io.AddressFamily.Ip4
.
void close()
Closes a previously opened socket, does nothing if the file is not opened. This function always succeeds.
Sometimes it may be convenient to use disposable pattern to ensure
timely invokation of close
[2].
bool errorcode connect(io.SocketAddress const* address)
Initiates a connection request to address
. This function is only
valid for TCP
sockets.
This method initiates a connection request and returns immediatly.
After connection request completes, an event io.SocketEvents.TcpConnected
(on success) or io.SocketEvents.IoError
(on failure) gets fired.
Returns true
on success. If a connection could not be established,
IO error supplied by operating system is set and then the function
returns false
[1].
bool errorcode listen(size_t backlog = 0)
Places a server socket into listen
state. This function is only
valid for TCP
sockets.
The only argument of the method, backlog
, specifies the maximum
length of the queue of pending client-side connections, i.e.
connections which has not been accepted via accept
method yet.
Returns true
on success. If the socket could not be placed into
listen
state, IO error supplied by operating system is set and then
the function returns false
[1].
io.Socket* errorcode accept( io.SocketAddress* address = null, bool isSuspended = false )
Accepts a client connection and returns a resulting io.Socket
object
to communicate with this particular client. To terminate a client
connection, issue close
method on the client file stream object.
If method fails, null
value is returned [1].
void unsuspend()
Accepted sockets may initially be suspended (so that the user has a
chance to configure reading options such as m_readBlockSize
)
Call unsuspend
to awaken the accepted socket after it has been
configured.
size_t errorcode write( void const* p, size_t size )
Attempts to send size
bytes from the buffer pointed to by p
over
the connected socket.
Returns the actual amount of bytes written on success. If write operation
is unsuccessful, IO error supplied by the operating system is set and
then the function returns -1
[1].
If the return value shows less bytes than specified by size
argument, you should suspend further transmission until the file stream
is ready to accept more data. When this happens, WriteBufferReady
event is fired and transmission could be resumed.
size_t errorcode readDatagram( void* p, size_t size, io.SocketAddress* address )
Attempts to read up to size
bytes from the socket into the buffer
pointed to by p
; stores the address of the sender into the
address
.
Returns the actual amount of bytes read on success. If read operation is
unsuccessful, IO error supplied by the operating system is set and then
the function returns -1
[1].
Normally you would call this function from within your event handler for
IncomingData
event.
size_t errorcode writeDatagram( void const* p, size_t size, io.SocketAddress const* address )
Attempts to send size
bytes from the buffer pointed to by p
to
the remote node pointed to by address
.
Returns the actual amount of bytes written on success. If write
operation is unsuccessful, IO error supplied by the operating system is
set and then the function returns -1
[1].
If the return value shows less bytes than specified by size
argument, you should suspend further transmission until the file stream
is ready to accept more data. When this happens, WriteBufferReady
event is fired and transmission could be resumed.
Aliases
alias dispose = close
Effectively makes io.Socket
a disposable class [2].
Footnotes