Chilkat.Socket concept guide

Socket Sets: One Event Loop, Many Connections

A socket set lets one Chilkat.Socket object coordinate multiple listener and connected sockets. Instead of blocking on one connection at a time, the application waits for whichever sockets are ready, selects one, and performs the appropriate operation through the set object.

1Build the set
2Wait for readiness
3Select a result
4Accept, read, or write

The idea in one sentence

A socket set is a Socket object that owns multiple member sockets. It can wait for several sockets at once, report which members are ready, and route ordinary socket operations to the member selected by SelectorIndex, SelectorReadIndex, or SelectorWriteIndex.

Core behavior
The set-level methods identify ready members. After selecting one of those members, calls such as AcceptNext, ReceiveString, SendBytes, and Close operate on that selected socket.
Visual model: one set, several socket roles
A Chilkat socket set containing one listener and three connected sockets The set object contains multiple member sockets. One is a listener and three are established client connections. Operations are routed to the selected member. Chilkat.Socket set object Owns members and routes operations to the active selection Listener socket Ready when a client is pending Connected socket A Read / write application data Connected socket B Independent connection Connected socket C Independent connection Incoming client Connects to listener Remote peers Data arrives independently Your event loop Select → choose → act

A set may contain listener sockets and established connections at the same time. The application must remember which members are listeners because the set does not label the ready socket's role.

Where socket sets are useful

Socket sets are most helpful when several independent sockets may need attention, but the application wants a single coordinating loop rather than a separate blocking wait for every connection.

Server

One listener plus many clients

Keep a listener and all accepted client connections in one set. When the listener is read-ready, call AcceptNext. When a connected socket is read-ready, call a receive method.

Client

Many outbound connections

A monitoring tool, gateway, or test harness can connect to many remote systems and wait until any one of them returns data.

Responsiveness

Polling without blocking

Pass 0 to SelectForReading or SelectForWriting to poll immediately, allowing the application to perform other work between checks.

Flow control

Wait for write readiness

SelectForWriting identifies sockets that can currently accept data into the operating-system send path without blocking. This does not mean the remote application has received or processed the data.

Building a socket set with TakeSocket

A normal Chilkat.Socket object becomes a socket set after one or more successful calls to TakeSocket. Each call moves the source connection into a newly created member of the set.

1

Create or obtain sockets

Connect outbound sockets, create a listener, or accept connections using ordinary socket objects.

2

Move them into the set

Call socketSet.TakeSocket(sourceSocket) for each connection or listener to be managed.

3

Use the set object

After selection, call ordinary methods on socketSet; Chilkat routes the call to the selected member.

TakeSocket moves ownership into the set
TakeSocket moving three source sockets into a set Three source socket wrappers transfer their connections to a socket set. The source wrappers are left empty after the move. Socket set member 0 member 1 member 2 source socket A connection moves out source socket B connection moves out source socket C connection moves out After success, each source object is empty and may be reused or destroyed.
Do not confuse TakeSocket with TakeConnection. TakeSocket adds a new member to a socket set. TakeConnection moves a connection into the receiving object itself and is not a set-building method.

The three selector properties

A selector tells the set which member should receive ordinary method calls and property access. The three selectors are mutually exclusive: assigning any one clears the other two.

Selector What the number means When to use it
SelectorIndex A direct position in the contained set: 0 through NumSocketsInSet - 1. When the application already knows which set member it wants.
SelectorReadIndex A position in the read-ready result returned by the most recent SelectForReading. While iterating sockets that are ready for accept or receive activity.
SelectorWriteIndex A position in the write-ready result returned by the most recent SelectForWriting. While iterating sockets that can currently accept a write without blocking.
The most important socket-set rule After a select call, assign the ready position directly to SelectorReadIndex or SelectorWriteIndex. Do not translate it into SelectorIndex. Setting SelectorIndex would clear the ready selection and reinterpret the number as a direct set position.

The canonical read-ready loop

SelectForReading returns the number of ready sockets, 0 for no readiness before the timeout, or -1 for an error. When it returns a positive value, iterate the ready positions and route operations through the set object.

The set resolves the ready index for you
Socket set read selection workflow SelectForReading produces a ready set. The application assigns each ready position to SelectorReadIndex and then calls AcceptNext or a receive method on the socket set object. SelectForReading returns n ready sockets n > 0 Read-ready result ready index 0 ready index 1 ready index 2 For each i = 0 … n − 1 SelectorReadIndex = i Then call on the set object: AcceptNext or ReceiveXxx No conversion to SelectorIndex is needed. The set routes the operation directly to the selected ready socket.
n = socketSet.SelectForReading(timeoutMs)

if n == -1
    // Handle select error.
else
    for i = 0 to n - 1
        socketSet.SelectorReadIndex = i

        if selected member is a listener
            socketSet.AcceptNext(destinationSocket, acceptTimeoutMs)
        else
            socketSet.ReceiveXxx(...)
        end if
    next
end if
Track socket roles in your own application state. A listener and a connected socket can both appear in the same read-ready result. The set does not tell you which kind was selected, so your code must know whether to call AcceptNext or a receive method.

What “ready” actually means

Socket type Read-ready means Typical next call
Listener An incoming connection is pending. AcceptNext
Connected socket Data is available, or a close/error condition can now be detected. A receive method, followed by failure-state handling if needed.
Read-ready does not guarantee application data. A receive can report that the peer closed or reset the connection. Readiness means the next operation should not remain blocked waiting for an event; it does not promise that the event is a successful data message.
Write-ready is also local. It means the socket can currently accept a write into the local networking path without blocking. It does not prove that the remote application received, parsed, or accepted the data.

Ready-set order and index lifetime

The ready-set order is stable while you iterate one select result, but the order is arbitrary. It does not have to match the order in which sockets were added, and it may change on the next select call.

Direct indexes

SelectorIndex refers to the current contained-set position. If a member is removed, later positions shift down, so a saved direct index may identify a different member or become invalid.

Ready indexes

SelectorReadIndex and SelectorWriteIndex are temporary positions in the current ready result. The next call to either select method invalidates all prior ready indexes.

Reliable rule: Treat selector indexes as short-lived. Use them inside one select-and-iterate cycle, and select again after removals or before beginning a new cycle.

Closing, removing, and pruning members

There is no separate “remove without closing” operation for a contained member. Select the member and call Close; the selected socket is closed and removed from the set immediately.

Explicit close

Set a selector, call Close on the set object, and Chilkat routes the close to the selected member. Direct set positions after that member shift down.

Automatic pruning

A connection that has died may remain counted until the next SelectForReading or SelectForWriting. Each select rebuilds the descriptor set and removes members that no longer have a usable descriptor.

// Remove direct member 3.
socketSet.SelectorIndex = 3
socketSet.Close(maxWaitMs)

// Do not reuse old direct indexes without reconsidering the new set order.

Use-case walkthrough: a compact multi-client server

The following design keeps one listener and several accepted client connections in the same set. The application maintains a small side table that records whether each member is a listener or a client connection.

  1. Create and bind a listener socket.
  2. Move the listener into the set with TakeSocket.
  3. Call SelectForReading.
  4. For each ready position, assign SelectorReadIndex.
  5. If the selected member is the listener, accept into a new socket and move the accepted socket into the set.
  6. Otherwise, receive and process client data.
  7. When a client closes or fails, select it and call Close to remove it.
// Conceptual pseudocode. Exact syntax varies by language.
listener.BindAndListen(port, backlog)
socketSet.TakeSocket(listener)
mark member as LISTENER

while running
    n = socketSet.SelectForReading(1000)
    if n < 0
        handle select error
        break
    end if

    for i = 0 to n - 1
        socketSet.SelectorReadIndex = i

        if selected member is LISTENER
            accepted = new Socket
            if socketSet.AcceptNext(accepted, 0)
                socketSet.TakeSocket(accepted)
                mark new member as CLIENT
            end if
        else
            if not socketSet.ReceiveXxx(...)
                // Handle close/error, then remove the selected member.
                socketSet.Close(0)
            end if
        end if
    next
end while
This structure is intentionally language-neutral. In production code, keep stable application metadata outside the numeric selector indexes, because direct set positions can change after removals.

Common mistakes

×
Copying a ready index into SelectorIndex.
Use SelectorReadIndex or SelectorWriteIndex directly.
×
Assuming ready-set order equals insertion order.
The order is arbitrary and may change on the next select.
×
Saving selector indexes as permanent connection IDs.
Indexes are routing positions, not stable application identities.
×
Assuming every read-ready socket has data.
A connected socket may instead be reporting a close or error condition.
×
Using TakeConnection to build the set.
TakeSocket adds set members; TakeConnection does not.

Quick reference

  • Use TakeSocket to move sockets into the set.
  • Use NumSocketsInSet to inspect the current contained count.
  • Use SelectorIndex only for a direct current set position.
  • After SelectForReading, set SelectorReadIndex directly.
  • After SelectForWriting, set SelectorWriteIndex directly.
  • Track listener-versus-connection roles in your application.
  • Call Close on a selected member to close and remove it.
  • Re-select after the set changes; do not reuse old indexes.