I have a chat client class
class ChatClient
{
Task ConnectAsync(string server);
Task SendMessageAsync(string message);
Task DisconnectAsync();
}
Once the user has connected with ConnectAsync they are able to call SendMessageAsync to send messages to other users.
Under the hood there is a Connection class which is a very basic wrapper for the Socket class. One of the main differences is that it has an OnError event.
I'm also using an observable message stream (reactive extensions) which reads from the connection and produces a stream of incoming commands from the server.
My question is this - when the socket produces an error, from where am I best to handle this error from? Should I handle it inside the OnError event handler, or should I intercept the error from the observable stream and handle it there?
I can't see any upside or downside either way, so I'm wondering what best practice dictates?
Something about having an event on a connection class has always struck me as being a little hacky, but I don't know why.
Any suggestions? Thanks
I would have to say that the best solution is which ever is most transparent to the end user. If the error affects the user in some way they should be notified or be given the choice of how to proceed. If it is not possible to notify the user then handle the error in a way that allows for easy future improvements.
Related
I'm working on a C# Docker application, where I am creating a microservice in order to handle TCP socket communication. This works, but it seems to be very unstable (some packets pass, some not). I have added a log entry, which might explain something (it's about sending a message over a TCP socket):
Source code (shown on multiple lines, but it's a oneliner):
Debug.WriteLine(
$"T[{System.Threading.Thread.CurrentThread.ManagedThreadId}],
{DateTime.UtcNow}: Handle().
Trying to send [{Message}] to [{ConnectionName}]");
Results:
T[14], 12/14/2022 15:26:08: Handle(). Trying to send [abc] to [XL_Test]
T[19], 12/14/2022 15:26:32: Handle(). Trying to send [abc] to [XL_Test]
As you can see, apparently my application always uses another thread to handle the requests. So, I'm left with a very simple question: is multithreaded programming allowed when working with TCP sockets?
For your information: I have already worked with multithreaded applications on TCP sockets before, where one thread was used for regular checking the connection and another for sending the messages, but here I have one thread which regularly checks the connection, while for sending messages, always another thread gets opened.
Edit: I don't know if this is helpful, but the name of the thread, handling the message, is .Net ThreadPool Worker.
Edit2: this is the way this Send() method is called:
await _mediator.Send(command);
... where _mediator is an IMediator from the MediatR library.
The first comment refers to another StackOverflow post which is using locks, but while trying this, I got a compilation error:
object lockobject = new object();
lock(lockobject)
{
await _mediator.Send(command);
}
The compiler message is CS1996: Cannot await in the body of a lock statement. (Pardon my ignorance, but I'm very new at this)
I'm using NServiceBus with RabbitMQ in my project. I have two services that don't know about each other and don't share anything. service1 publishes request messages to endpoint1 (queue1) and service2 listens to endpoint1 and publishes responses to endpoint2 (queue2). There are two questions:
How can service1 handle responses from service2 if service1 doesn't know the response message type but only expects some particular fields in the response message?
I want to create an async API method that sends a request to endpoint1 and waits for the response in endpoint2. Is it somehow possible at all? Also how can I ensure that the reply corresponds with the request?
I expect something like:
public async Task<object> SendRequest(string str) {
var request = new MyRequest(str);
await endPoint1.Publish(request);
var reply = await endPoint2.WaitingReply();
return reply;
}
I will appreciate any help.
Whenever two things communicate, there is always a contract. When functions call each other the contract is the parameters that are required to call that function. With messaging the message is the contract. The coupling is towards the message, not the sender or receiver.
I'm not really sure what you're trying to achieve? You mention an API which is async and endpoint1 and endpoint2.
First of all, there's asynchronous execution and asynchronous communication. The async part in your example code is asynchronous execution of two methods that have the word await in front of them. When we talk about sending messages, that's asynchronous communication. A message is put on the queue and then the code moves on and never looks back at the message. Even when you use the request/reply pattern, no code is actually waiting for a message.
You can wait for a message by blocking the thread, but I highly recommend you avoid that and not use the NServiceBus callback feature. If you think you have to, think again. If you still think so, read the red remarks on that page. If they can't convince you, contact Particular Software to have them explain another time why not. ;-)
It could be that you need a reply message for whatever reason. If you build some website using SignalR (for example) and you want to inform the user on the website when a message returned and some work was completed, you can wait for a reply message. The result is that the website itself becomes an endpoint.
So if the website is EndpointA and it sends a message to EndpointB, it is possible to reply to that message. EndpointA would then also need a message handler for that message. If EndpointB first needs to send a message to EndpointC, which in turn responds to EndpointB and only then it replies back to EndpointA, NServiceBus can't easily help. Not because it's impossible, but because you probably need another solution. EndpointA should probably not be waiting for that many endpoints to reply, so many things could go "wrong" and take too much time.
If you're interested to see how replies work in combination with SignalR and what not, you can check a demo I built for a presentation that has that.
How can I send a message (or publish an event) when a message runs out of retries and moves to the error queue?
When a request comes into my system, I create a Saga to track it. The Saga sends commands to Handlers to do async work. If the handler fails, I want to both move that command to the error queue (the default behavior) and send a message to the Saga to alert the client that originally requested the work.
I have tried customizing the recoverability behavior to use the Saga as the error queue, which sends the command back but does not get it into the error queue:
recoverability.CustomPolicy((config, context) =>
{
// invocation of default recoverability policy
var action = DefaultRecoverabilityPolicy.Invoke(config, context);
if (action is MoveToError)
{
return RecoverabilityAction.MoveToError("SagaEndpoint");
}
return action;
});
Another thing I tried was using a Behavior to hook into the Pipeline, but there does not seem to be a a way to override the "move to error queue" step. I can create an IIncomingLogicalMessageContext and try/catch around the await next();, but that triggers for each retry instead of just the final one. I also tried an IOutgoingLogicalMessageContext, but that does not get invoked when a message moves to the error queue. If I missed something, that could be a solution.
I also know I can use a timeout in the Saga to guess when the Handler fails. But I would rather not wait for a timeout if the failure is quick or risk timing out if the work takes longer than expected.
I found this older question that sounds like it's asking the same thing, but the answer is incomplete and uses the older EventHandler Notifications instead of the newer Task-based Notifications. If there is a way to access an IMessageSession or IEndpointInstance from the Notification callback, I think that would work for me as well.
There's not an "easy" way to do that because at the moment when recoverability is happening, any transaction related to the incoming message (this is different for each transport) is in doubt, so you can't really do anything else within the scope of what's going on right at that moment.
Once you start your endpoint, you can cast the IEndpointInstance to an IMessageSession (same thing without things like the Stop method) and then assign that to a place where your "error queue notifier" will be able to find it. Then any operation you do with the IMessageSession will basically be a separate context, disconnected from the processing of the incoming message.
Just understand that if the message is failing processing because of an underlying problem with the queue, that's not going to report correctly. That's why most people would be doing some sort of call to a reporting/diagnostics service in those callbacks.
I have a request/response protocol that runs over TCP that I'd like to provide an async/await API for. The protocol is STOMP, which is a fairly simple text-based protocol that runs over TCP or SSL. In STOMP, the client sends one of six or so command frames and specifies a receipt ID in the header of the command. The server will respond with either a RECEIPT or ERROR frame, with a receipt-id field, so the client can match the response with the original request. The server can also send a MESSAGE frame at any time (STOMP is fundamentally a messaging protocol) which will not contain a receipt-id.
To allow multiple outstanding requests and handle any MESSAGE frames, the plan is to always have a Socket.BeginReceive() outstanding. So what I was thinking is that the easiest implementation would be to create a waitable event (like a mutex), store that event in a table, send the command request with the receipt set to the index into the table, and block on the event. When socket.BeginReceive() fires the function can get the receipt-id from the message, look up the event in the table, and signal it (and store some state, like success or error). This will wake up the calling function, which can look at the result and return success or failure to the calling application.
Does this sound fundamentally correct? I've used async/await APIs before but have never written my own. If it's OK what kind of waitable event should I use? A simple Monitor.Wait() will block but not in the way I want, correct? If I wrap the whole thing in Task.Run() will that behave properly with Monitor.Wait()? Or is there a new synchronization construct that I should be using instead? I'm basically implementing HttpClient.GetAsync(), does anyone know how that works under the covers?
HttpClient is much simpler, because HTTP only has one response for each request. There's no such thing as an unsolicited server message in HTTP.
To properly set up a "stream" of events like this, it's best to use TPL Dataflow or Rx. Otherwise, you'd have to create an unbounded receive buffer and have repeated async ReceiveMessage calls.
So I'd recommend using a TPL Dataflow pipeline to create a source block of "messages", and then matching some up with requests (using TaskCompletionSource to notify the sender it's complete) and exposing the rest (MESSAGE frames) as a source block.
Internally, your processing pipeline would look like this:
Repeated BeginReceive ->
TransformBlock for message framing ->
ActionBlock to match response messages to requests.
BufferBlock for MESSAGE frames.
I run my application on a network and in some cases the client lost connection to the server. After this time, when I wanted to send a message to the server I receive the following error: Operation not allowed on non-connected sockets (something like this).
I thought to create an event for object type TcpClient and when tcp_obj.Connected = false to call a function to discontinue execution of the current code. How could I do this?
Or giving me other suggestios.
Thanks.
I know at least from socket programming in Java that when a client loses connection to the server, the server does not and can not know about it. You need a heartbeat of some sort to detect the early disconnection.
We often use a heartbeat in our client/server applications to detect early disconnections and log them on the server. This way the server can close the associated socket and release the connection back to the pool.
Simply send a command to the client periodically and wait for a response. If no response is garnered within a timeout assume disconnect and close streams.
I would simply first check your connection object to ensure you are connected, prior to attempting to send the message. Also make sure that you are putting your send-logic inside of a try-catch, so that if you do happen to get disconnected mid transmission, you'll be able to resume without blowing your application apart.
Psuedo-Code:
private void SendMessage(string message, Socket socket)
{
if(socket.connectionState = States.Connected)
{
try{
// Attempt to Send
}
catch(SocketException Ex)
{
// Disconenct, Additional Cleanup Etc.
}
}
}
If you are in C#, prior to your connection state changing, you will have a socket disconnected event fire, prior to your connection state changing. Make sure you tie this event up as soon as your socket connects.
Can we know why you use TCP sockets? Is for calling a tcp device o server code?
I recommend you if is for calling a .net server app use Windows Communication Foudation. It is simple to expose services by net.tcp, http, etc.
Regards,
Actually this is a very old problem,
If I understand your question correctly you need a way to know whether you're application is still connected to the server or vice versa.
If so then a workaround is to have a UDP connection just to check the connectivity (overhead I know, but its much better then polling on Connected state), you could check just before you send you're data.
Since UDP is not Connection oriented you don't need to be connected when you send the data