AVCoders.CommunicationClients
2026.11.1
Prefix Reserved
dotnet add package AVCoders.CommunicationClients --version 2026.11.1
NuGet\Install-Package AVCoders.CommunicationClients -Version 2026.11.1
<PackageReference Include="AVCoders.CommunicationClients" Version="2026.11.1" />
<PackageVersion Include="AVCoders.CommunicationClients" Version="2026.11.1" />
<PackageReference Include="AVCoders.CommunicationClients" />
paket add AVCoders.CommunicationClients --version 2026.11.1
#r "nuget: AVCoders.CommunicationClients, 2026.11.1"
#:package AVCoders.CommunicationClients@2026.11.1
#addin nuget:?package=AVCoders.CommunicationClients&version=2026.11.1
#tool nuget:?package=AVCoders.CommunicationClients&version=2026.11.1
AVCoders.CommunicationClients
Transport clients for the AV Coders device library — the concrete CommunicationClient implementations that drivers talk to hardware through. Built on AVCoders.Core. Targets .NET 8.0 and .NET 10.0.
Install
dotnet add package AVCoders.CommunicationClients
Published to nuget.org. See the repository README for details.
Transports
AvCodersTcpClient- Reads are decoded as Latin-1 (one character per byte, the encoding
Bytes.FromStringsends), or as the\xNNdump whenCommandStringFormatisn'tAscii. - While connected, the connection is checked every second, so a dropped connection is retried within about a second. After a failed attempt it waits 1 s, doubling up to 20 s; a good connection starts it at 1 s again.
- An attempt that hasn't connected within 5 s is ended and reported as the
connectionissue "The connection attempt to host:port timed out". Its exception goes inErrorsand is logged at Debug, not Error. Every other failed attempt, refused and unreachable included, logs its exception as an Error. A failed attempt's socket is closed at once. - A failed write closes that connection once and keeps the message at the head of the send queue, so it goes out first, in order, after the reconnect. A queued message whose write fails is timestamped again, so the queue timeout counts from the failure; the messages queued behind it keep their own timestamps. The SSH client does the same.
Reconnect()closes the open connection, if there is one, and starts a connection attempt at once with the backoff back at 1 s. While an attempt is already running it only resets the backoff.
- Reads are decoded as Latin-1 (one character per byte, the encoding
AvCodersUdpClient- Retries opening its socket every 5 s until it opens, whether the host is an IP address or a host name, and reports each failed attempt as the
connectionissue. The failure is logged when it first happens and when its reason changes, not on every retry. A host name that resolves to no addresses is reported as "The host name was not found". - Receives block until a datagram arrives. Datagrams are decoded as Latin-1, or as the
\xNNdump whenCommandStringFormatisn'tAscii. - A failed send keeps the datagram at the head of the send queue and reopens the socket, as the TCP client does, and a queued datagram whose send fails is timestamped again. A failed direct send reopens it on a task, so the caller doesn't wait on a host name lookup.
- A device whose port is closed (ICMP port unreachable, seen on the next receive) is reported as the
connectionissue, with no state change and no new socket. The next datagram received resolves it.
- Retries opening its socket every 5 s until it opens, whether the host is an IP address or a host name, and reports each failed attempt as the
AvCodersSshClient- After a failed connection attempt it waits 60 s before the next one. When the device rejects the credentials it waits 5 minutes instead, and the
connectionissue says so: "SSH authentication to host was rejected for user X; the next attempt is in 5 minutes". Connect()andReconnect()start a connection attempt at once, ending either wait and resetting the short-session backoff.Disconnect()ends the wait and stays disconnected.- Each write and its flush hold one lock, so messages from senders on different threads, and from the send queue, reach the shell stream whole and in the order they were written.
- The receive worker reads when the shell stream signals data (
DataReceived) or that it closed (Closed), instead of checking every 10 ms. An idle session wakes it no times a second instead of about 100. Lines are still read one at a time, in order, on that worker, and a closed shell still sets Error at once.
- After a failed connection attempt it waits 60 s before the next one. When the device rejects the credentials it waits 5 minutes instead, and the
AvCodersMqttClientAvCodersRestClientAvCodersMulticastClient- Binds on its connection worker, retrying with a 1–20 s backoff. A failed bind, a dead socket and a group that isn't an IP address (logged with the value as given) are reported as the
connectionissue; the constructor doesn't throw. A dead socket is rebound at once; one that dies again before it has stayed bound through a 30 s check is rebound after the bind backoff. - An IPv6 group binds to
IPv6Any, and the TTL sets its multicast hop limit. - Text is sent and received as Latin-1, one character per byte, as the TCP client does;
Bytes.FromStringsends a character above U+00FF as?. Received datagrams are the\xNNdump instead whenCommandStringFormatisn'tAscii. The request handlers are raised only for a datagram that was sent.
- Binds on its connection worker, retrying with a 1–20 s backoff. A failed bind, a dead socket and a group that isn't an IP address (logged with the value as given) are reported as the
AvCodersTcpServerConnect()listens and accepts,Disconnect()stops listening, drops the clients and setsDesiredConnectionStateto Disconnected, andReconnect()restarts accepting and keeps the clients.- A failed bind or a dead listener is reported as the
connectionissue, and the listener is rebound at once with a 1–20 s backoff.Disconnectedis set as soon as the last client leaves. - Each write to a client times out after 5 s; a client whose write fails is dropped and the other clients still get the send.
- Text is sent and received as Latin-1, one character per byte, as the TCP client does;
Bytes.FromStringsends a character above U+00FF as?. Reads are the\xNNdump instead whenCommandStringFormatisn'tAscii.
AvCodersSnmpV3ClientGet,SetandWalkreturn anSnmpReply: the variables, plus the RFC 3416ErrorStatusandErrorIndexas received. A reply with a non-zero error status counts as an answer: the client stays Connected, raises noconnectionissue, and returns no variables with the status and index, which the traffic log shows aserror status GenError (5), index 1. A timeout, an unreachable host or rejected credentials returns no variables, sets Error and reports theconnectionissue.
AvCodersWakeOnLanWakereturns at once and sends the three rounds of packets to ports 7 and 9, 300 ms apart, on a task. An invalid MAC is logged with the value as given and nothing is sent.
Why a client isn't connected
Every client has ConnectionReason beside ConnectionState (see the AVCoders.Core README). ConnectionState keeps its values and when they're set. The reason is set on each failed attempt, with the connection issue's text as its Description, and cleared when the client connects.
| Category | Set when |
|---|---|
TimedOut |
A socket timeout, the TCP or MQTT 5 s connect timeout, an SSH operation timeout, or an SNMP or REST request timeout |
Refused |
The connection is refused, or a UDP or SNMP datagram gets ICMP port unreachable back (ConnectionReset on Windows, ConnectionRefused on Linux) |
HostNotFound |
The host name doesn't resolve, or resolves to no addresses |
Unreachable |
The host or the network is unreachable |
CredentialsRejected |
SSH authentication is rejected; a REST request gets 401 or 403; an SNMPv3 agent reports an unknown user, a wrong auth or privacy password, or an unsupported security level; an MQTT broker answers BadUserNameOrPassword or NotAuthorized |
ClosedByDevice |
The connection is reset, or the SSH server ends the session ("An established connection was aborted by the server.") |
Requested |
Disconnect() was called. Connect() clears it |
Other |
Anything else, with the raw text |
- An SSH session that fails after it connected (the stream's
ErrorOccurred, such as the Navigator dropping the session) sets the reason without raising theconnectionissue, and the exception is still logged as an Error. Reconnecting clears it. - A REST 401 or 403 sets
CredentialsRejectedand raises theconnectionissue "host:port rejected the credentials for /path: 401 Unauthorized", which escalates like any other connection failure. The client stays Connected. The next 2xx response clears the reason and resolves the issue. AvCodersModbusRtuClientmirrors its transport's reason.- The TCP, SSH and UDP clients set
DesiredConnectionStateto Connected in their constructors, where they start connecting, so it no longer reads Unknown.Connect()isn't called, so the send queue and the workers are left as they are.
Reconnect on the next send a person makes
- The TCP, SSH and UDP clients' and
AvCodersTcpServer'sDisconnect()recordsActor.CurrentasDisconnectedByand turnsReconnectOnSendon when there is one (a browser, MCP or a panel) and off when there isn't (a driver or the program). Both are set beforeDesiredConnectionStatechanges, so the state and reason handlers already see them. - A
Disconnect()while the client is already disconnected on request keepsDisconnectedByandReconnectOnSendas they are. - While the client is disconnected on request with
ReconnectOnSendon, a send made under anActor, directly or through its driver, callsConnect()and then goes out.ReconnectingForSendis true from then until the client is connected, or disconnected again. - Each send made under an
ActorwhileReconnectingForSendis true is queued until the client connects, and is sent if that's within 15 s, or within the queue timeout when that is longer. Every other queued send, polls included, keeps the queue timeout (5 s by default,SetQueueTimeout). - The UDP client opens its socket inside
Connect(), so the send goes out at once when the socket opens. When it doesn't, the send is queued as above and the socket is retried every 5 s. - A
Connect()whileReconnectingForSendis true keeps the send queue. Any otherConnect()clears it, as before. - A send with no
Actor(a poll or any otherThreadWorkerpass, a command a driver sends from a reply or a timer) is dropped with a Debug log, as is every send whileReconnectOnSendis off. Connect(),Disconnect(),SetReconnectOnSendand a person's send while disconnected on request run one at a time on each client. A second caller waits until the first has finished; a TCP or UDP disconnect takes milliseconds, an SSH disconnect can take a second or two while SSH.NET waits for the server to close the channel, and a UDP connect to a host name waits for DNS. Sends while connected and polls never wait.SetReconnectOnSend(bool)changes it.Connect()turns it off and clearsDisconnectedBy, and the nextDisconnect()sets both again. Each change ofReconnectOnSendis logged at Information and added toEvents.ReconnectOnSendHandlersis raised on each change ofReconnectOnSendorDisconnectedBy. The reconnect is logged at Information with the sender's actor andDisconnectedBy.AvCodersTcpServerhas no peers to send to while it's disconnected, so that send callsConnect(), which starts it listening again for its peers to reconnect, and is dropped with an Information log.AvCodersMulticastClientnever sets it.
Usage
A driver is decoupled from how it is connected — you construct a transport and hand it to the driver:
var comms = new AvCodersTcpClient("192.168.1.50", 4352, "Projector", CommandStringFormat.Ascii);
Trigger ids, queues and headers
RequestHandlers/RequestByteHandlers(tx) are raised when the bytes are written, not when a send is queued.- The TCP, SSH and UDP offline send queues store the sender's
Trigger.Idwith each payload, and send it, or log its timeout or overflow drop, underTrigger.Resume(id). - The UDP send queue drains once the client has a socket. Only sends younger than the queue timeout (5 s by default, set with
SetQueueTimeout) go out; older ones are dropped. - Each SSH line,
AvCodersTcpServerread and MQTT message received outside aThreadWorkerpass starts a new trigger id. AvCodersRestClient, and every otherHttpClientthe drivers create, use aSocketsHttpHandlerwithActivityHeadersPropagator = null: requests carry notraceparent,tracestate,baggageorCorrelation-Contextheaders, including when sent from inside an ASP.NET Core request (an MCP call or a Blazor event).AvCodersMqttClientconnects and reconnects from oneThreadWorker. While not connected, each pass makes oneConnectAsyncattempt, and the next pass starts 3 s after that attempt ends. An attempt that hasn't connected within 5 s, including one to a broker that accepts the TCP connection and never answers the CONNECT, is ended and reported as theconnectionissue "The connection attempt to host:port timed out". While connected, each pass only setsConnectionStateto Connected. A failed attempt, a dropped connection or a publish while disconnected doesn't start another loop. A broker that rejects the CONNECT (e.g. bad credentials) is reported as theconnectionissue.- The MQTT worker doesn't inherit the actor or trigger id of the code that created the client. Each pass starts its own trigger id, and MQTTnet's receive and keep-alive loops carry the id of the pass that connected them.
AvCodersMqttClientraisesRequestHandlersoncePublishAsynccompletes. A publish while disconnected is logged and dropped, not queued. Topics subscribed while disconnected are subscribed on connect. On each connect every subscribed topic's SUBSCRIBE is sent beforeConnectionStatebecomes Connected, so a publish from aConnectionStateHandlersConnected handler reaches the broker after them. A message reaches the handlers of every subscribed topic filter it matches,+and#wildcards included. Failed publishes and subscribes are logged, and so is a subscription the broker refuses in its SUBACK (e.g. NotAuthorized).
See the repository README for full wiring examples.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- AVCoders.Core (>= 2026.11.1)
- Lextm.SharpSnmpLib (>= 12.5.7)
- MQTTnet (>= 5.0.1.1416)
- SSH.NET (>= 2026.0.0)
-
net8.0
- AVCoders.Core (>= 2026.11.1)
- Lextm.SharpSnmpLib (>= 12.5.7)
- MQTTnet (>= 5.0.1.1416)
- SSH.NET (>= 2026.0.0)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on AVCoders.CommunicationClients:
| Package | Downloads |
|---|---|
|
AVCoders.Power
PDU and outlet drivers for the AV Coders device library, including Eaton (SNMP) and ServerEdge (REST). |
|
|
AVCoders.Conference
Conferencing codec drivers for the AV Coders device library, including Cisco RoomOS control, output/microphone faders and phonebook parsing. |
|
|
AVCoders.Crestron.CommunicationClients
AV Coders communication clients backed by Crestron hardware: serial over COM ports, IR ports driven as serial, DM CEC streams, multicast UDP and generic-device IP status. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2026.11.1 | 0 | 11/12/2026 |
| 2026.10.5 | 137 | 10/21/2026 |
| 2026.10.4 | 128 | 10/21/2026 |
| 2026.10.3 | 201 | 10/14/2026 |
| 2026.10.2 | 125 | 10/13/2026 |
| 2026.10.1 | 152 | 10/6/2026 |
| 2026.9.8 | 154 | 9/29/2026 |
| 2026.9.7 | 147 | 9/24/2026 |
| 2026.9.6 | 145 | 9/18/2026 |
| 2026.9.5 | 146 | 9/17/2026 |
| 2026.9.4 | 206 | 9/14/2026 |
| 2026.9.2 | 161 | 9/2/2026 |
| 2026.9.1 | 148 | 9/2/2026 |
| 2026.8.5 | 148 | 8/27/2026 |
| 2026.8.4 | 158 | 8/26/2026 |
| 2026.8.3 | 160 | 8/26/2026 |
| 2026.8.2 | 172 | 8/24/2026 |
| 2026.8.1 | 204 | 8/11/2026 |
| 2026.7.3 | 166 | 7/22/2026 |
| 2026.7.2 | 212 | 7/21/2026 |