question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ConnectAsync stuck in .NET 4.x framework when ExtraHeaders in SocketIOOptions are used

See original GitHub issue

Hi @doghappy,

I found an issue with this library when used with .NET framework 4.x series (tested on 4.6 - 4.8). The ConnectAsync function seems to be stuck in an infinite loop when I pass ExtraHeaders to SocketIO constructor options. The client does not even seem to initiate handshake to the server. Without ExtraHeaders in SocketIOOptions, the ConnectAsync function establishes a connection to the server as expected. None of the SocketIO events are triggered on client and server side when supplying ExtraHeaders. I am unable to debug where the code is stuck as debugger does not seem to provide any useful information.

This issue seems to be affected in .NET Framework 4.x series only. The below code works without any change in .net6.0 and others.

Here is my client code

// C#
using System;
using SocketIOClient;

var socketIOOptions = new SocketIOOptions
{
    //EIO = 4,
    Auth = new Dictionary<string, string> { { "user", "test" }, { "token", "test" }, },
    //ConnectionTimeout = TimeSpan.FromSeconds(10),
    Reconnection = true,
    ReconnectionAttempts = 5,
    Transport = SocketIOClient.Transport.TransportProtocol.WebSocket,
    ExtraHeaders = new Dictionary<string, string> { { "User-Agent", "dotnet-socketio[client]/socket" } }
};

var io = new SocketIO("http://localhost:8000", socketIOOptions);

io.On("seq-num", e => Console.WriteLine(e));
io.OnConnected += async (s, e) => Console.WriteLine("Connected!");
io.OnDisconnected += async (s, e) => Console.WriteLine("Disconnected!");
io.OnError += async (s, e) => Console.WriteLine("Error!");
io.OnPing += async (s, e) => Console.WriteLine("Ping!");
io.OnPong += async (s, e) => Console.WriteLine("Pong!");
io.OnReconnectAttempt += async (s, e) => Console.WriteLine("Reconnecting!");
io.OnReconnected += async (s, e) => Console.WriteLine("Reconnected!");
io.OnReconnectError += async (s, e) => Console.WriteLine("Reconnect Error!");
io.OnReconnectFailed += async (s, e) => Console.WriteLine("Reconnect Failed!");

await io.ConnectAsync();

await Task.Delay(100000);

And here is the server code that I used to test it.

// JS
const
    {Server} = require("socket.io"),
    server = new Server(8000);

let
    sequenceNumberByClient = new Map();

// event fired every time a new client connects:
server.use( (socket, next) => {
  console.log(socket.handshake);
  if (socket.handshake.auth && socket.handshake.auth.user && socket.handshake.auth.user == "test") {
    next();
  } else {
    next(new Error("Invalid User!"));
  }
})
.on("connection", (socket) => {
    console.info(`Client connected [id=${socket.id}]`);
    // initialize this client's sequence number
    sequenceNumberByClient.set(socket, 1);

    // when socket disconnects, remove it from the list:
    socket.on("disconnect", () => {
        sequenceNumberByClient.delete(socket);
        console.info(`Client gone [id=${socket.id}]`);
    });
});

// sends each client its current sequence number
setInterval(() => {
    for (const [client, sequenceNumber] of sequenceNumberByClient.entries()) {
        client.emit("seq-num", sequenceNumber);
        sequenceNumberByClient.set(client, sequenceNumber + 1);
    }
}, 3000);

My project file

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net462</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
	  <LangVersion>10.0</LangVersion>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="SocketIOClient" Version="3.0.6" />
  </ItemGroup>

</Project>

Issue Analytics

  • State:closed
  • Created 10 months ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
useraccessdeniedcommented, Nov 29, 2022

Thanks for the effort!

One more thing. Issue #290 seems to be the same as this. The user also sets User-Agent there and he might not know it was due to .net framework 4.x.

1reaction
useraccessdeniedcommented, Nov 27, 2022

How about this solution? (StackOverflow.com) Modify HeaderInfoTable with reflection

Here, read-only IsRequestRestricted is modified using reflection to false and then it won’t throw error on setting property as usual. This will work for both ClientWebSocket and HTTPWebRequest.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Socket Class (System.Net.Sockets)
The Socket class allows you to perform both synchronous and asynchronous data transfer using any of the communication protocols listed in the ProtocolType ......
Read more >
Best HTTP Released | Page 13
We have recently used Best HTTP in our app to download asset bundle resources ... returns only the Uri, but not the parameters...
Read more >
doghappy/socket.io-client-csharp
Socket.IO-client for .NET. An elegant socket.io client for .NET, it supports socket.io server v2/v3/v4, and has implemented http polling and websocket.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found