Build the protocol on top of the byte stream
Reliable socket code begins with one fact: a connected
Chilkat.Socket presents an ordered byte stream, not a sequence of
application messages. The same application-facing stream is used whether the
connection is plain, protected by TLS, or carried through an SSH tunnel.
Chilkat handles the TLS or SSH protocol details internally; your application
reads and writes ordinary bytes. It must still define message boundaries,
choose receive methods that match those boundaries, use explicit timeouts,
and handle partial I/O correctly.
1. A byte stream does not preserve messages
A successful send places bytes into the connected byte stream. The receiver may obtain those bytes in different-sized pieces, and the boundaries between send calls are not preserved. This application-level behavior is the same for a plain connection, TLS, or a connection carried through an SSH tunnel.
SendXxx and ReceiveXxx methods
for a plain socket, TLS, or a connection opened through an SSH tunnel. Chilkat
performs encryption, decryption, TLS record processing, and SSH packet handling
internally. Those protocol details do not change the application's framing rules:
the application still sees one ordered byte stream.
One send can require several receives, and one receive can contain bytes from several sends.
ReceivePacketSize is not a message-size setting.
For a plain TCP connection it limits the amount requested by one underlying
availability-based read. It does not create or preserve application message
boundaries. TLS and SSH receive sizes are governed by their own record or packet
processing, and already-buffered data may exceed ReceivePacketSize.
2. Every protocol needs a framing rule
The receiver must know when a complete application message has arrived. Without a framing rule, it cannot distinguish “the message is complete” from “more bytes have not arrived yet.”
Fixed length
Every message or field has a predetermined byte count. This is simple and efficient when the protocol truly uses fixed-size records.
Use exact-length methods such as ReceiveBytesN or
ReceiveBdN.
Length prefix
Send a fixed-size integer first, followed by that many payload bytes. Both sides must agree on integer width, signedness, and byte order.
Chilkat provides SendCount, ReceiveCount, and
explicit 16-bit and 32-bit integer methods.
Delimiter
End a message with an agreed byte sequence such as CRLF, a line-feed, or a protocol-specific marker.
Use ReceiveUntilMatch, ReceiveToCRLF, or a
byte-delimiter receive method.
Length-prefixed message
ReceiveCount returns a signed
32-bit value and reserves -1 as its failure result. Its byte order is
controlled by BigEndian, which defaults to network byte order.
Delimiter-based message
Delimiter matching is byte-oriented. For ReceiveUntilMatch, Chilkat
encodes the match string using StringCharset and performs an exact,
case-sensitive byte comparison. A match may span several underlying network
reads.
| Method | Delimiter | Returned data | Important behavior |
|---|---|---|---|
ReceiveUntilMatch |
matchStr encoded with StringCharset |
Text through and including the match | Exact, case-sensitive byte match; partial content is discarded on failure. |
ReceiveUntilMatchSb |
Same as above | Appends text through and including the match | The destination is unchanged on failure, but consumed bytes are not recoverable. |
ReceiveToCRLF |
CR+LF encoded with StringCharset |
Text including the line terminator | Usually matches 0D 0A with ASCII-compatible encodings. |
ReceiveUntilByteBd |
One raw byte | Appends bytes including the delimiter | Partial bytes remain in the BinData destination on failure. |
ReceiveStringUntilByte |
One raw byte | Text preceding the delimiter | A non-ASCII delimiter can split a multibyte encoded character. |
3. Choose the receive method by its contract
Chilkat offers several receive families because they solve different protocol problems. Choosing by data type alone is not enough; choose by completion rule.
| Receive contract | Representative methods | When the call completes | Failure considerations |
|---|---|---|---|
| One available delivery |
ReceiveBytesReceiveBdReceiveStringReceiveSb
|
Returns internally buffered data first; otherwise performs one receive operation. It does not drain the entire connection. | An orderly close is reported as failure, but final bytes received with the close can still be present in the output. |
| Exactly N bytes |
ReceiveBytesNReceiveBdNReceiveNBytesENC
|
Continues until the requested count is satisfied or a receive failure occurs. | Partial-output behavior differs by method. Read the specific method description before deciding whether a failed call's destination is usable. |
| Through a delimiter |
ReceiveUntilMatchReceiveUntilByteBdReceiveToCRLF
|
Continues until the configured delimiter is found. | Some methods retain partial data on failure; others discard it. Delimiter inclusion also varies. |
| Fixed-size integer |
ReceiveByteReceiveInt16ReceiveInt32ReceiveCount
|
Requires the complete 1-, 2-, or 4-byte value. | A failed partial integer read consumes and discards the bytes already read, which can leave the protocol stream misaligned. |
ReceivedCount. Always check the specific receive method's failure
contract.
Integer receive results
ReceiveByte, ReceiveInt16, and
ReceiveInt32 place a successful result in
ReceivedInt. A failed call does not clear that property; it retains
the value from the last successful integer receive.
success = socket.ReceiveInt32(true)
if success:
value = socket.ReceivedInt
else:
reason = socket.ReceiveFailReason
# Do not use ReceivedInt here; it may be stale.
4. Sending, buffering, and backpressure
A synchronous Chilkat send method encodes or accepts the application's data and attempts to move the resulting bytes through the connection. Chilkat and the operating system may buffer outgoing data, so early sends can complete quickly. If the application produces data faster than the connection or peer can accept it, the send eventually waits for additional progress. This is called backpressure. For TLS and SSH connections, Chilkat handles the security-protocol framing internally.
false result from SendBytes,
SendBd, or SendString does not prove that zero bytes
reached the peer. Chilkat does not retain the unsent remainder and does not report
how many bytes were transmitted. For a length-prefixed, delimited, or otherwise
framed protocol, the safest recovery is usually to close the connection and start
a new session.
SendString adds no length prefix or terminator. It only encodes the
string using StringCharset and sends the resulting bytes. Any message
framing must be added by the application.
5. Understand the different timeout scopes
Socket timeouts are not all interchangeable. The timeout argument passed to
Connect governs connection establishment, while
MaxReadIdleMs and MaxSendIdleMs govern periods with no
I/O progress.
| Phase or operation | Primary control | Meaning |
|---|---|---|
| DNS lookup and connection establishment | Connect(..., maxWaitMs) |
An overall connection-establishment budget. A value of 0
means wait indefinitely, subject to an internal practical ceiling.
|
| Receive methods | MaxReadIdleMs |
Maximum continuous period with no received byte. The timer resets whenever read progress occurs. |
| Send methods | MaxSendIdleMs |
Maximum continuous period with no sent byte. The timer resets whenever write progress occurs. |
| TLS handshake | MaxReadIdleMs and MaxSendIdleMs |
The TLS handshake exchanges protocol data after the underlying network connection is established. Chilkat handles this exchange internally. |
| HTTP/SOCKS proxy negotiation | Read/write idle timeouts | No separate proxy-negotiation timeout property is provided. |
MaxReadIdleMs or
MaxSendIdleMs as long as bytes continue to move. A value of
0 disables the corresponding idle timeout and permits an indefinite
wait. Use finite values for externally controlled peers.
6. Treat return values as authoritative
A Boolean return value should be checked before inspecting result properties. Capture any matching failure reason immediately after the operation.
| Property | What it describes | Why immediate capture matters |
|---|---|---|
ConnectFailReason |
The most recent connect-family operation | It can retain an older reason until another connect begins. |
AcceptFailReason |
The most recent accept operation | Unrelated operations do not clear it. |
ReceiveFailReason |
The most recent receive-side operation | It can remain set while sends and other methods are called. |
SendFailReason |
The most recent send-side operation | It can remain set until the next send begins. |
LastMethodFailed |
The most recent action method | A later helper or certificate method can overwrite it. |
ReceivedInt |
The last successful integer receive | A failed integer receive leaves the previous value unchanged. |
IsConnected is also a last-known state, not a guarantee. An idle
application is not continuously notified that a peer or network path has
vanished. The property may remain true until a read, write, or other socket
operation detects the loss.
success = socket.SendBytes(data)
if not success:
reason = socket.SendFailReason
errorText = socket.LastErrorText
# Capture these before calling another action method.
7. The byte stream carries bytes, not characters
Text-oriented methods use StringCharset to convert between application
strings and wire bytes. Both peers must agree on the same encoding.
utf-8.
The default value ansi means the system default encoding determined by
the default system locale. It is not a fixed encoding such as Windows-1252,
ISO-8859-1, or ASCII, and it can differ between computers.
Use byte-oriented methods for binary protocols or whenever exact byte preservation
matters. Also remember that delimiter methods compare encoded bytes. For example,
ReceiveToCRLF searches for CR+LF encoded with
StringCharset; with UTF-8 that is 0D 0A, while a
UTF-16 encoding produces a wider byte sequence.
8. Secure the connection deliberately
TLS adds confidentiality and peer authentication, but the relevant checks are controlled separately.
| Setting | Purpose | Practical guidance |
|---|---|---|
RequireSslCertVerify |
Validates certificate dates, signatures, and trusted certificate chain. | The default is false. Enable it for a normal TLS client unless a controlled environment intentionally uses a different trust model. |
SniHostname |
Sets the SNI name sent in the TLS ClientHello. |
Usually the hostname passed to Connect is used. Set this when
connecting to an IP address or alternate endpoint for a named virtual host.
|
TlsPinSet |
Requires the server public key to match one of the configured SPKI pins. | Pinning is enforced independently of normal chain verification. Plan for server key rotation by configuring backup pins in advance. |
SslProtocol |
Limits allowed TLS protocol versions. |
Prefer default or a minimum such as
TLS 1.2 or higher. Avoid SSL 3.0, TLS 1.0, and TLS 1.1.
|
SslAllowedCiphers |
Restricts allowed cipher suites or selects a policy keyword. |
Leave empty unless interoperability or policy requires a restriction.
best-practices applies Chilkat's current policy.
|
TlsVersion and TlsCipherSuite are retained from the most
recent successful TLS handshake. They are not cleared by Close, a
failed connection, a later non-TLS connection, or ConvertFromSsl.
Do not use them alone to decide whether the current connection is protected by TLS.
9. Multiple connections: socket sets
A socket set allows one Socket object to own multiple listener and/or
connected sockets and wait for readiness across the group. It is useful for servers,
multiplexed clients, and event-loop designs that should not block on one connection
while another is ready.
n = socketSet.SelectForReading(timeoutMs)
for i = 0 to n - 1:
socketSet.SelectorReadIndex = i
# Operations now route to the i-th read-ready socket.
# Call AcceptNext for a listener or ReceiveXxx for a connection.
SelectorIndex.
SelectorReadIndex, SelectorWriteIndex, and
SelectorIndex are mutually exclusive. Assign the read-ready or
write-ready position directly to the corresponding ready selector.
See the Socket Sets Overview for the complete ownership, selection, readiness, removal, and index-lifetime rules.
10. A practical implementation checklist
MaxReadIdleMs and MaxSendIdleMs.IsConnected as a guarantee of future success.