An elegant socket.io client for .NET, it supports socket.io server v2/v3/v4, and has implemented http polling and websocket.
Connect to the socket.io server, listen events and emit some data.
var client = new SocketIO("http://localhost:11000/");
client.On("hi", response =>
{
// You can print the returned data first to decide what to do next.
// output: ["hi client"]
Console.WriteLine(response);
string text = response.GetValue<string>();
// The socket.io server code looks like this:
// socket.emit('hi', 'hi client');
});
client.On("test", response =>
{
// You can print the returned data first to decide what to do next.
// output: ["ok",{"id":1,"name":"tom"}]
Console.WriteLine(response);
// Get the first data in the response
string text = response.GetValue<string>();
// Get the second data in the response
var dto = response.GetValue<TestDTO>(1);
// The socket.io server code looks like this:
// socket.emit('hi', 'ok', { id: 1, name: 'tom'});
});
client.OnConnected += async (sender, e) =>
{
// Emit a string
await client.EmitAsync("hi", "socket.io");
// Emit a string and an object
var dto = new TestDTO { Id = 123, Name = "bob" };
await client.EmitAsync("register", "source", dto);
};
await client.ConnectAsync();
The way to override the default options is as follows:
var client = new SocketIO("http://localhost:11000/", new SocketIOOptions
{
Query = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("token", "abc123"),
new KeyValuePair<string, string>("key", "value")
}
});
Option | Default value | Description |
---|---|---|
Path |
/socket.io |
name of the path that is captured on the server side |
Reconnection |
true |
whether to reconnect automatically |
ReconnectionAttempts |
int.MaxValue |
number of reconnection attempts before giving up |
ReconnectionDelay |
1000 |
how long to initially wait before attempting a new reconnection. Affected by +/- RandomizationFactor , for example the default initial delay will be between 500 to 1500ms. |
RandomizationFactor |
0.5 |
0 <= RandomizationFactor <= 1 |
ConnectionTimeout |
20000 |
connection timeout |
Query |
IEnumerable<KeyValuePair<string, string>> |
additional query parameters that are sent when connecting a namespace (then found in socket.handshake.query object on the server-side) |
EIO |
V4 |
If your server is using socket.io server v2.x, please explicitly set it to V3 |
ExtraHeaders |
null |
Headers that will be passed for each request to the server (via xhr-polling and via websockets). These values then can be used during handshake or for special proxies. |
Transport |
Polling |
Websocket is used by default, you can change to http polling. |
AutoUpgrade |
true |
If websocket is available, it will be automatically upgrade to use websocket |
Auth |
null |
Credentials that are sent when accessing a namespace |
Client
await client.EmitAsync("ack", response =>
{
// You can print the returned data first to decide what to do next.
// output: [{"result":true,"message":"Prometheus - server"}]
Console.WriteLine(response);
var result = response.GetValue<BaseResult>();
}, "Prometheus");
Server
socket.on("ack", (name, fn) => {
fn({
result: true,
message: `${name} - server`
});
});
Client
client.On("ack2", async response =>
{
// You can print the returned data first to decide what to do next.
// output: [1, 2]
Console.WriteLine(response);
int a = response.GetValue<int>();
int b = response.GetValue<int>(1);
await response.CallbackAsync(b, a);
});
Server
socket.emit("ack2", 1, 2, (arg1, arg2) => {
console.log(`arg1: ${arg1}, arg2: ${arg2}`);
});
The output of the server is:
arg1: 2, arg2: 1
This example shows how to emit and receive binary messages, The library uses System.Text.Json to serialize and deserialize json by default.
class FileDTO
{
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("mimeType")]
public string MimeType { get; set; }
[JsonPropertyName("bytes")]
public byte[] Bytes { get; set; }
}
client.OnConnected += async (sender, e) =>
{
await client.EmitAsync("upload", new FileDTO
{
Name = "template.html"
MimeType = "text/html",
bytes = Encoding.UTF8.GetBytes("<div>test</div>")
});
};
client.On("new files", response =>
{
// You can print the returned data first to decide what to do next.
// output: [{"name":"template.html","mimeType":"text/html","bytes":{"_placeholder":true,"num":0}}]
Console.WriteLine(response);
var result = response.GetValue<FileDTO>();
Console.WriteLine(Encoding.UTF8.GetString(result.Bytes))
});
Based on the Target Framework you used to install the package, the default json serializer will be imported for you.
Target Framework | Serializer | Package | Example |
---|---|---|---|
.NET Standard 2.0 | System.Text.Json | SocketIO.Serializer.NewtonsoftJson |
client.Serializer = new SystemTextJsonSerializer(new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); |
.NET Framework 4.6.2 | Newtonsoft.Json | SocketIO.Serializer.NewtonsoftJson |
client.Serializer = new NewtonsoftJsonSerializer(new JsonSerializerSettings { ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() } }); |
.NET Standard 2.0 | Message Pack | SocketIO.Serializer.MessagePack |
client.Serializer = new SocketIOMessagePackSerializer(); |
This table assumes that you're using System.Text.Json for .NET Standard 2.0 and Newtonsoft.Json for .NET Framework 4.6.2, but you can use either serializer with either target framework if you prefer.
If you want to change JsonSerializerOptions, you can do this:
serializer = new SystemTextJsonSerializer(new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
var client = new SocketIO("http://localhost:11000/", serializer: serializer);
Of course you can also use Newtonsoft.Json library, for this, you need to install SocketIO.Serializer.NewtonsoftJson
dependency.
client.Serializer = new NewtonsoftJsonSerializer(new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new CamelCaseNamingStrategy()
}
});
The library uses System.Net.WebSockets.ClientWebSocket by default. Unfortunately, it does not support Windows 7 or Windows Server 2008 R2. You will get a PlatformNotSupportedException. To solve this problem, you need to install the SocketIOClient.Windows7
dependency and then change the implementation of ClientWebSocket.
client.ClientWebSocketProvider = () => new ClientWebSocketManaged();
The library will always try to connect to the server, and an exception will be thrown when the connection fails. The library catches some exception types, such as: TimeoutException, WebSocketException, HttpRequestException and OperationCanceledException. If it is one of them, the library will continue to try to connect to the server. If there are other exceptions, the library will stop reconnecting and throw exception to the upper layer. You need extra attention in Xamarin.
For Xamarin.Android you should add the following code:
public partial class MainPage: ContentPage
{
public MainPage()
{
InitializeComponent();
}
public SocketIO Socket {get;}
}
...
public class MainActivity: global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
...
var app = new App();
var mainPage = app.MainPage as MainPage;
mainPage.Socket.AddExpectedException(typeof(Java.Net.SocketException));
mainPage.Socket.AddExpectedException(typeof(Java.Net.SocketTimeoutException));
LoadApplication(app);
}
...
}
I don't know the specific exceptions of Xamarin.iOS. Welcome to create a pr and update this document. thanks :)
- The default serializer might change depending on the target framework your project is targeting by default.
- Any of the serializers should work for either Target Framework (with the exception of Message Pack as it is .NET Standard 2.0+)
- See Json Serializer Options for more details
- Changed all projects to target both .net standard 2.0 and .net 4.6.2
- Except
SocketIO.Serializer.MessagePack
- Except
- Changed
SocketIO
constructor to includeISerializer
ISerializer
defaults to first available based on target framework- .net 4.6.2
SocketIO.Serializer.NewtonsoftJson
- .net Standard 2.0+
SocketIO.Serializer.SystemTextJson
- .net 4.6.2
- Changed
EventHandlers
delegates to invokeobject
arrays instead ofJsonElement
arrays
Thank socket.io and darrachequesne for sponsoring the project on Open Collective.
We would like to thank JetBrains for supporting the project with free licenses of their fantastic tools.