Backend API. Server-side code: this runs in a Codename One backend, not in the app on the device.

public final class ServerSocket

  1. Object
  2. ServerSocket
A listening TCP socket and the blocking read/write a worker uses once it owns a connection. Deliberately fd-based rather than object-per-socket: the reactor deals in descriptors and an extra object per idle connection is exactly the cost this design exists to avoid.

Nested types

class ServerSocket.TimeoutExceptionThrown when a read or write deadline expires.

Methods

public static ServerSocket bind(String host, int port, int backlog) throws IOException
  • host: null or “0.0.0.0” to listen on every interface - port: 0 to let the OS choose, then ask getPort
public int getFd()
public int getPort()
public int accept()The accepted descriptor, or -1 when nothing was waiting.
public void close()
public static void setBlocking(int fd, boolean blocking) throws IOExceptionBlocking or non-blocking mode for one descriptor.
public static void setTimeout(int fd, int millis) throws IOExceptionApplies a receive and send deadline.
public static byte[] readIntoThreadBuffer(int fd, int capacity)Read from fd into this thread’s reusable buffer and return an array whose length is exactly the number of bytes read, or null at end of stream.
public static byte[] threadReadBuffer(int capacity)A reusable per-thread read buffer of at least capacity bytes.
public static boolean awaitReadable(int fd, int timeoutMillis) throws IOExceptionWaits for the socket to become readable, for at most timeoutMillis.
public static int read(int fd, byte[] buffer, int offset, int length) throws IOException-1 at end of stream, as InputStream does.
public static void write(int fd, byte[] buffer, int offset, int length) throws IOException
public static void closeFd(int fd)
public static void setReceiveTimeout(int fd, int millis) throws IOExceptionThe RECEIVE deadline alone, leaving the send deadline where it is.
public static void shutdown(int fd)Breaks a descriptor in both directions without closing it.
public static byte[] peerAddress(int fd)The address of a connection’s other end as its raw bytes – 4 for IPv4, 16 for IPv6 – or null when the descriptor is not a connected socket.
public static int availableProcessors()Cores available to this process.

Inherited methods

Method details

bind

public static ServerSocket bind(String host, int port, int backlog) throws IOException
  • host: null or “0.0.0.0” to listen on every interface
  • port: 0 to let the OS choose, then ask getPort

getFd

public int getFd()

getPort

public int getPort()

accept

public int accept()
The accepted descriptor, or -1 when nothing was waiting.

close

public void close()

setBlocking

public static void setBlocking(int fd, boolean blocking) throws IOException
Blocking or non-blocking mode for one descriptor. The reactor needs non-blocking; a worker that owns a connection wants blocking, so it can read a request without a state machine.

setTimeout

public static void setTimeout(int fd, int millis) throws IOException
Applies a receive and send deadline. Without one a connection that opens and says nothing holds a worker forever, and the pool is bounded.

readIntoThreadBuffer

public static byte[] readIntoThreadBuffer(int fd, int capacity)

Read from fd into this thread’s reusable buffer and return an array whose length is exactly the number of bytes read, or null at end of stream.

On the translated target this allocates nothing and copies nothing: the array header and its storage are C memory the collector never touches, and the length is set per read so the caller can scan to array.length. Java SE cannot resize an array and returns a right-sized copy instead – same contract, different allocation accounting.

The bytes belong to the current callback on the current thread. Anything that must outlive either has to be copied out first.

threadReadBuffer

public static byte[] threadReadBuffer(int capacity)

A reusable per-thread read buffer of at least capacity bytes.

The same array comes back on every call for a thread, so a server that reads through it allocates nothing per request. Its contents belong to the current callback only – the next read on this thread overwrites them, so nothing may retain it or hand it to code that might.

On the translated target the storage is a C buffer that the collector never allocated and never sweeps, so the read path contributes nothing at all to the allocation rate that paces the GC. Java SE cannot do that and returns an ordinary cached array; the observable contract is the same, which is the point – only the allocation accounting differs.

awaitReadable

public static boolean awaitReadable(int fd, int timeoutMillis) throws IOException

Waits for the socket to become readable, for at most timeoutMillis. True if it is, false if the wait expired.

One syscall, and it leaves the descriptor exactly as it was. The caller uses it between requests on a keep-alive connection, where the alternatives – setting and restoring a receive deadline, or flipping to non-blocking and back – cost two to four syscalls each way and disturb the deadline that governs a real request read.

read

public static int read(int fd, byte[] buffer, int offset, int length) throws IOException
-1 at end of stream, as InputStream does.

write

public static void write(int fd, byte[] buffer, int offset, int length) throws IOException

closeFd

public static void closeFd(int fd)

setReceiveTimeout

public static void setReceiveTimeout(int fd, int millis) throws IOException

The RECEIVE deadline alone, leaving the send deadline where it is.

setTimeout sets both, which is right for a request – a peer that stops reading blocks a worker in send() just as effectively as one that stops writing. A websocket wants them apart: it is idle by design, so its read allowance is minutes or nothing at all, while a send to a peer that has stopped reading must still give up. Using setTimeout for that quietly moved the send bound from fifteen seconds to five minutes, and CN1_WS_IDLE_TIMEOUT_MS=0 removed it entirely.

shutdown

public static void shutdown(int fd)

Breaks a descriptor in both directions without closing it.

For the one case a close cannot serve: a thread is parked inside a write to a peer that has stopped reading, and the connection has to go NOW. A close would free the number while that thread still holds it, and the number is reused immediately – so the write lands in whatever connection was handed it next. shutdown(2) makes the parked write fail instead, and the close follows once the writer has left.

Quiet about failure on purpose: every reason it can fail (the peer already went, the descriptor was already shut) is a state the caller wanted anyway.

peerAddress

public static byte[] peerAddress(int fd)
The address of a connection’s other end as its raw bytes – 4 for IPv4, 16 for IPv6 – or null when the descriptor is not a connected socket.

availableProcessors

public static int availableProcessors()
Cores available to this process.