Connect an .NET WebSockets client to a node.js socket.io server - c#

I am currently supporting an older application which has a node.js (v0.12.13) server with a socket.io (v1.3.7) connection. This server supports a browser clients very well.
socket.attach(http, { 'transports': ['polling','websocket'], 'allowUpgrades': true });
socket.attach(https, { 'transports': ['polling','websocket'], 'allowUpgrades': true });
socket.sockets.on('connection', function (socket) {
// Process stuff here
});
Our requirements also required that we allow our legacy Windows app to connect to the node server and I had used SocketIoClientDotNet/EngineIoClientDotNet, and this more or less works OK (with some exceptions that I need to handle).
So I thought I would try to use a .NET ClientWebSocket approach, where uri="ws://10.10.5.112", based on this article:
static async Task Connect(string uri)
{
ClientWebSocket sock = new ClientWebSocket();
await sock.ConnectAsync(new Uri(uri), CancellationToken.None);
}
But I get the following exceptions:
System.AggregateException
HResult=0x80131500
Message=One or more errors occurred.
Source=mscorlib
StackTrace:
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait()
at WebsocketClientTest.Program.Main(String[] args) in C:\Source\test\WebsocketClientTest\Program.cs:line 16
Inner Exception 1:
WebSocketException: Unable to connect to the remote server
Inner Exception 2:
WebException: The underlying connection was closed: The connection was closed unexpectedly.
Sure enough, I don't see any connection attempt at the server, but Wireshark is telling me that the .Net app is trying to initiate the connection, but gets no response from the node.js server. Looks like this a failure at the socket.io side, but any ideas to help me along are appreciated.

Related

GRPC - The HTTP/2 server sent invalid data on the connection. HTTP/2 error code 'PROTOCOL_ERROR when upgrading from .netcore 3.1 to net5 or net6

I have a .netcore3.1 test project which calls a GRPC service.
The service is only available via HTTP. I cannot change the service now.
When I update the project to .net5-windows or .net6-windows (literally only a csproj change), the calls fail with the following error:
Grpc.Core.RpcException : Status(StatusCode="Unavailable", Detail="Error starting gRPC call. HttpRequestException: An error occurred while sending the request. IOException: The request was aborted. Http2ConnectionException: The HTTP/2 server sent invalid data on the connection. HTTP/2 error code 'PROTOCOL_ERROR' (0x1).", DebugException="System.Net.Http.HttpRequestException: An error occurred while sending the request.
---> System.IO.IOException: The request was aborted.
---> System.Net.Http.Http2ConnectionException: The HTTP/2 server sent invalid data on the connection. HTTP/2 error code 'PROTOCOL_ERROR' (0x1).
at System.Net.Http.Http2Connection.ThrowProtocolError(Http2ProtocolErrorCode errorCode)
at System.Net.Http.Http2Connection.ReadFrameAsync(Boolean initialFrame)
at System.Net.Http.Http2Connection.ProcessIncomingFramesAsync()
--- End of inner exception stack trace ---
at System.Net.Http.Http2Connection.ThrowRequestAborted(Exception innerException)
at System.Net.Http.Http2Connection.Http2Stream.CheckResponseBodyState()
at System.Net.Http.Http2Connection.Http2Stream.TryEnsureHeaders()
at System.Net.Http.Http2Connection.Http2Stream.ReadResponseHeadersAsync(CancellationToken cancellationToken)
at System.Net.Http.Http2Connection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.Http2Connection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at Grpc.Net.Client.Web.GrpcWebHandler.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
at Grpc.Net.Client.Internal.GrpcCall2.RunCall(HttpRequestMessage request, Nullable1 timeout)")
at..
I had a look at few SO questions (e.g. .Net Core 3.1 gRPC client with unencrypted HTTP2 connection and Grpc.Core.RpcException: 'Status (StatusCode = "Unavailable", Detail = "Error starting gRPC call) as well as the 'call insecure service' troubleshooting guide https://learn.microsoft.com/en-us/aspnet/core/grpc/troubleshoot?view=aspnetcore-5.0#call-insecure-grpc-services-with-net-core-client however they are not helpful.
I have tried a few options of setting AppContext (even though they should apply for netcore3.1) like this before initializing a client, but again no help:
AppContext.SetSwitch(“System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport”, true);
AppContext.SetSwitch(“System.Net.Http.SocketsHttpHandler.Http2Support”, true);
The channel is initialized as follows:
var baseUri = new Uri(baseUrl);
HttpMessageHandler httpMessageHandler = new HttpClientHandler();
if (baseUri.AbsolutePath != "/")
httpMessageHandler = new SubDirectoryHandler(httpMessageHandler, baseUri.AbsolutePath);
var handler = new GrpcWebHandler(GrpcWebMode.GrpcWebText, httpMessageHandler);
_channel = GrpcChannel.ForAddress(baseUrl, new GrpcChannelOptions { HttpClient = new HttpClient(handler) });
Inspecting the GRPC channel before sending the request shows the request version is 1.1 (regardless of AppContext settings and TargetFramework):
The GRPC client libraries are:
Grpc.Net.Client v. 2.42.0
Grpc.Net.Client.Web v. 2.42.0
When the request is sent, the service side is logging the following in the output:
Exception thrown: 'Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException' in Microsoft.AspNetCore.Server.Kestrel.Core.dll
Exception thrown: 'Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException' in System.Private.CoreLib.dll
'TradingOrchestrationService.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App\6.0.5\Microsoft.AspNetCore.WebUtilities.dll'.
Exception thrown: 'System.Net.Sockets.SocketException' in Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll
The I/O operation has been aborted because of either a thread exit or an application request.
The key thing I'd like to stress is the only difference between working and non-working behaviour is bumping up TargetFramework version in the entry assembly from 3.1 to 5 or 6.
For completeness and future reference I am posting the replies that I got from JamesNK on GitHub https://github.com/dotnet/runtime/issues/71906
When using HTTP then the client and server must use the same protocol.
Without https then there is no negotiation.
What protocol is Kestrel configured to use? HTTP/1.1 or HTTP/2? If you
haven't explicitly configured it to only HTTP/2 then it will probably
be HTTP/1.1.
GrpcWebHandler has a HttpVersion property on it that you can set to
explicitly specify what HTTP version you want. You could try setting
it to new Version(1, 1).
Does setting this property have any other implications?
And when we migrate the server to use HTTP/2, I suppose it will have to be removed?
Yes
What happened to you: in .NET Core 3.x the gRPC client was configuring
the gRPC request to be HTTP/2, but because you weren't using TLS the
request was silently downgraded to HTTP/1.1
That was fixed in .NET 5+, but you were relying on broken behavior so
the fix broke you.
The client is now sending HTTP/2 over http, but your server is
configured for HTTP/1.1. That creates a protocol error.
GrpcWebHandler.HttpVersion provides a way for you to override the HTTP
version and to specify exactly what you want (because gRPC-Web works
with both HTTP versions).

how to know why WCF service stopped

We have developed WCF service and hosted as windows service. We have written .net core client application.
We have observed that the service is not responding after a few calls. It gets stopped somehow.
I tried to create logging and trace in WCF service but it is not creating any .svclog file.
In exception handling, it gives the following message
Exception: One or more errors occurred. (An error occurred while
sending the request.) System.ServiceModel.CommunicationException: An
error occurred while sending the request. --->
System.Net.Http.HttpRequestException: An error occurred while sending
the request. ---> System.IO.IOException: Unable to read data from the
transport connection: An existing connection was forcibly closed by
the remote host.. ---> System.Net.Sockets.SocketException (10054): An
existing connection was forcibly closed by the remote host. --- End
of inner exception stack trace --- at
System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError
error, CancellationToken cancellationToken) at
System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.GetResult(Int16
token) at
System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage
request, CancellationToken cancellationToken)
I want to know what forced the service to be stopped? How can I find this?

Getting "System.Net.WebException: The underlying connection was closed: The connection was closed unexpectedly." error while calling web api

In my application, there is a functionality to extract reports based on a date range. In the background, it is calling my Web API with authentication(A), which consists of api caller functionality using httpclient, which is calling another non-secured DMZ server API (B) and a DMZ API-caliing WCF service (C) to collect data from the database.
My problem is that whenever I select a large date range, I get the following error in my WebAPI (A).
System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The underlying connection was closed: The connection was closed unexpectedly.
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
--- End of inner exception stack trace ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at LRAS.OrderServices.Core.Helpers.ApiCaller.d__4.MoveNext()
What I have tried: I have increased the httpclient timeout from 300 to 1000 seconds, but it is breaking nearly every minute.
You can try several methods:
1.Configure the service point security protocol and select the SecurityProtocolType that suits you (Tls12, Ssl3, Tls, Tls11).
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
C# System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send
2.Set the ConnectionClose property of HttpClient.
_client.DefaultRequestHeaders.ConnectionClose = true;
HttpClient throwing "An error occurred while sending the request."
3.Try to hold the request long enough for it to complete normally and receive a valid response.
_client.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
_client.DefaultRequestHeaders.Add("Keep-Alive", "3600");
.NET HttpClient - An existing connection was forcibly closed by the remote host

when trying to connect to IPFS System.Net.Http.HttpRequestException: No connection could be made because the target machine actively refused it

I am trying to upload a file to Ipfs below is my code sample.
using (var ipfs = new IpfsClient())
{
await ipfs.Swarm.Peers();
IpfsStream inputStream = new IpfsStream(filepath, System.IO.File.OpenRead(filepath));
MerkleNode node = await ipfs.Add(inputStream);
return Ok(node.Hash);
}
and i am getting error
System.Net.Http.HttpRequestException: No connection could be made because the target machine actively refused it.
---> System.Net.Sockets.SocketException (10061): No connection could be made because the target machine actively refused it.
at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
Any reasons my firewall is turned off so that cant be an issue. Any suggestions.
Is it correct approach to write file on ipfs.
The exception is giving you the answer. The remote server is denying the connection. Either the connection configuration is wrong at your end, or there's a mechanism at the service end that will only allow an incoming connection from certain places. Check both.

I'm getting a MailKit.Security.SslHandshakeException when trying to connect to "smtp.office365.com"

I am trying to use MailKit to send an email message via "smtp.office365.com". Here is the code I'm using.
using (var client = new SmtpClient(new ProtocolLogger("smtp.log")))
{
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.Connect("smtp.office365.com", 587, SecureSocketOptions.SslOnConnect);
client.Authenticate(new SaslMechanismNtlmIntegrated());
Debug.WriteLine(client.IsAuthenticated);
client.Send(message);
client.Disconnect(true);
}
The SaslMechanismNtlmIntegrated class I got from this comment on GitHub.
Whenever I run this code, I get an SslHandshakeException.
Here are the details of the exception:
MailKit.Security.SslHandshakeException
HResult=0x80131500
Message=An error occurred while attempting to establish an SSL or TLS connection.
One possibility is that you are trying to connect to a port which does not support SSL/TLS.
The other possibility is that the SSL certificate presented by the server is not trusted by the system for one or more of the following reasons:
1. The server is using a self-signed certificate which cannot be verified.
2. The local system is missing a Root or Intermediate certificate needed to verify the server's certificate.
3. The certificate presented by the server is expired or invalid.
See https://github.com/jstedfast/MailKit/blob/master/FAQ.md#InvalidSslCertificate for possible solutions.
Source=MailKit
StackTrace:
at MailKit.Net.Smtp.SmtpClient.<ConnectAsync>d__70.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MailKit.Net.Smtp.SmtpClient.Connect(String host, Int32 port, SecureSocketOptions options, CancellationToken cancellationToken)
at QuoteAndOrder.SpecialsQuoteWindow.BtnEmail_Click(Object sender, RoutedEventArgs e) in SpecialsQuoteWindow.xaml.cs:line 501
Inner Exception 1:
IOException: The handshake failed due to an unexpected packet format.
I went to the FAQ mentioned in the details, but the workaround given did not resolve the issue.
The solution mentioned by willaien resolved this issue. Namely, using SecureSocketOptions.StartTls instead of SecureSocketOptions.SslOnConnect.

Categories

Resources