Sockets Queue Issue - c#

hello all i have this issue , and i am stuck with it so any help will be greatly appreciated
i have to build a socket chat (client Server) module and i have done almost 80% of the work but now i am stuck , Scenario is that i have a server app and clients connect to it now if say 4 clients are connected to server each of them can communicate to each other , one client will send message and server will receive that message and will pass it along ,this is working very fine but when 2 or more clients send a message to 3rd client at the same time than i can not get one message and client get disconnected i know i have to build up a queue structure but i am not getting succeeded in it here
here is my code structure
StartReceive(SocketAsyncEventArgs) ->
First of all i call this method to start listening for incoming messages
and when i got one message i check if it is completed Sync or Async
and after this there is an io completed listener which is called every time one receive opertaion is completed and in that io completed method i do call processReceive method which is used to process received chunks
so finally my code structure is like this
StartReceive-> IO Completed -> ProcessReceive
i have designed the structure so that every client will have a Receive SOCKETASYNCEVENTAGRS
object and a Send SOCKETASYNCEVENTAGRS at server side and i do maintain a pool for this
so each client receives and sends data through its own SOCKETASYNCEVENTAGRS object
i want a scenario such that if two or more clients send messages to 3rd client than 3rd client should not receive all messages at the same time instead it should have a queue structure and it should receive one message at a time and same for send operation
here is some of my code
private void StartReceive(SocketAsyncEventArgs receiveSendEventArgs)
{
DataHoldingUserToken receiveSendToken = (DataHoldingUserToken)receiveSendEventArgs.UserToken;
receiveSendEventArgs.SetBuffer(receiveSendToken.bufferOffsetReceive, this.socketListenerSettings.BufferSize);
bool willRaiseEvent = receiveSendEventArgs.AcceptSocket.ReceiveAsync(receiveSendEventArgs);
if (!willRaiseEvent)
{
ProcessReceive(receiveSendEventArgs);
}
}
This is IO Completed
void IO_Completed(object sender, SocketAsyncEventArgs e)
{
DataHoldingUserToken receiveSendToken = (DataHoldingUserToken)e.UserToken;
switch (e.LastOperation)
{
case SocketAsyncOperation.Receive:
ProcessReceive(e);
break;
default:
}
}
and this is my StartReceive with Queue implemented but it is not working
Queue rec = new Queue();
bool IsExecuted = true;
private void StartReceive(SocketAsyncEventArgs receiveSendEventArgs)
{
if (IsExecuted)
{
DataHoldingUserToken receiveSendToken = (DataHoldingUserToken)receiveSendEventArgs.UserToken;
rec.Enqueue(receiveSendToken);
}
try
{
receiveSendEventArgs.SetBuffer(receiveSendToken.bufferOffsetReceive, this.socketListenerSettings.BufferSize);
bool willRaiseEvent = receiveSendEventArgs.AcceptSocket.ReceiveAsync(receiveSendEventArgs);
if (!willRaiseEvent)
{
ProcessReceive(receiveSendEventArgs);
}
rec.Dequeue();
IsExecuted = true;
}
catch
{
IsExecuted = false;
StartReceive(receiveSendEventArgs);
}
}
looking for a decent help or some good direction

I'm not sure if this is the root cause of your problem but it seems to me that you are running out of DataHoldingUserToken at some time because you are never doing anything with the objects you dequeue, hence you are throwing it away.
Also note that it is recommended to use the generic form of the Queue class for non-trivial object. That would be System.Collections.Generic.Queue<DataHoldingUserToken>.

Related

NetMQ response socket poll fails after succeeding one time

I'm new to the world of ZeroMQ and I'm working through the documentation of both NetMQ and ZeroMQ as I go. I'm currently implementing (or preparing to implement) the Paranoid Pirate Pattern, and hit a snag. I have a single app which is running the server(s), clients, and eventually queue, though I haven't implemented the queue yet. Right now, there should only be one server at a time running. I can launch as many clients as I like, all communicating with the single server. I am able to have my server "crash" and restart it (manually for now, automatically soon). That all works. Or at least, restarting the server works once.
To enforce that there's only a single server running, I have a thread (which I'll call the WatchThread) which opens a response socket that binds to an address and polls for messages. When the server dies, it signals its demise and the WatchThread decrements the count when it receives the signal. Here's the code snippet that is failing:
//This is the server's main loop:
public void Start(object? count)
{
num = (int)(count ?? -1);
_model.WriteMessage($"Server {num} up");
var rng = new Random();
using ResponseSocket server = new();
server.Bind(tcpLocalhost); //This is for talking to the clients
int cycles = 0;
while (true)
{
var message = server.ReceiveFrameString();
if (message == "Kill")
{
server.SendFrame("Dying");
return;
}
if (cycles++ > 3 && rng.Next(0, 16) == 0)
{
_model.WriteMessage($"Server {num} \"Crashing\"");
RequestSocket sock = new(); //This is for talking to the WatchThread
sock.Connect(WatchThreadString);
sock.SendFrame("Dying"); //This isn't working correctly
return;
}
if(cycles > 3 && rng.Next(0, 10) == 0)
{
_model.WriteMessage($"Server {num}: Slowdown");
Thread.Sleep(1000);
}
server.SendFrame($"Server{num}: {message}");
}
}
And here's the WatchThread code:
public const string WatchThreadString = "tcp://localhost:5000";
private void WatchServers()
{
_watchThread = new ResponseSocket(WatchThreadString);
_watchThread.ReceiveReady += OnWatchThreadOnReceiveReady;
while (_listen)
{
bool result = _watchThread.Poll(TimeSpan.FromMilliseconds(1000));
}
}
private void OnWatchThreadOnReceiveReady(object? s, NetMQSocketEventArgs a)
{
lock (_countLock)
{
ServerCount--;
}
_watchThread.ReceiveFrameBytes();
}
As you can see, it's pretty straight forward. What am I missing? It seems like what should happen is exactly what happens the first time everything is instantiated: The server is supposed to go down, so it opens a new socket to the pre-existing WatchThread and sends a frame. The WatchThread receives the message and decrements the counter appropriately. It's only on the second server where things don't behave as expected...
Edit: I was able to get it to work by unbinding/closing _watchThread and recreating it... it's definitely suboptimal and it still seems like I'm missing something. It's almost as if for some reason I can only use that socket once, though I have other request sockets being used multiple times.
Additional Edit:
My netstat output with 6 clients running (kubernetes is in my host file as 127.0.0.1 as is detailed here):
TCP 127.0.0.1:5555 MyComputerName:0 LISTENING
TCP 127.0.0.1:5555 kubernetes:64243 ESTABLISHED
TCP 127.0.0.1:5555 kubernetes:64261 ESTABLISHED
TCP 127.0.0.1:5555 kubernetes:64264 ESTABLISHED
TCP 127.0.0.1:5555 kubernetes:64269 ESTABLISHED
TCP 127.0.0.1:5555 kubernetes:64272 ESTABLISHED
TCP 127.0.0.1:5555 kubernetes:64273 ESTABLISHED

Correct pattern for ZeroMQ Server/Client type

I have a server that needs to get instructions to run processes for clients on another machine.
The clients send a job message, the Server processes the job and later sends the back results.
I tried using the NetMQ Request-Response pattern (see below)
This works nicely for 1 client, BUT if a second client sends a request before previous client job is finished - I get an error.
I really need to be able to receive ad-hoc messages from clients, and send results when they are completed. Clearly, I am using the wrong pattern, but reading the ZeroMQ docs has not highlighted a more appropriate one.
namespace Utils.ServerMQ
{
class ServerMQ
{
public static void Go()
{
using (var responseSocket = new ResponseSocket("#tcp://*:393"))
{
while (true)
{
Console.WriteLine("Server waiting");
var message = responseSocket.ReceiveFrameString();
Console.WriteLine("Server Received '{0}'", message);
//System.Threading.Thread.Sleep(1000);
var t2 = Task.Factory.StartNew(() =>
{
RunProcMatrix(message, responseSocket);
});
}
}
}
public static void RunProcMatrix(object state, ResponseSocket responseSocket)
{
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = Path.Combine(#"H:\Projects\Matrix\Matrix\bin\Debug\", "Matrix001.exe"),
Arguments = (string)state,
WindowStyle = ProcessWindowStyle.Normal,
CreateNoWindow = false
}
};
process.Start();
process.WaitForExit();
responseSocket.SendFrame((string)state);
}
}
}
You want a ROUTER socket on the server side, so it can receive multiple requests at a time. (Guide) REQ sockets on the client side are still fine unless the server may arbitrarily push data to them, then they need to be DEALER sockets.
Note that for sockets beyond REQ/RESP you need to manually handle the message envelope (the first frame of the message indicating its destination). Guide
The 0MQ docs are incredibly dense... I don't blame you for not intuiting this from them :)
This example from the NetMQ docs is full ROUTER-DEALER: https://netmq.readthedocs.io/en/latest/router-dealer/#router-dealer, you can take just the router side and it should work the same though.

websocket-sharp server sending duplicate messages

Here is the rumpus.
I am building a networked app using websocket-sharp and I have run into an issue where the server sends hundreds (not consistently the same amount) of duplicate messages to the client, heres the breakdown.
1.) The client connects (This handshake works fine).
2.) Upon client connection the server sends said client the session ID created for that connection. (This works)
3.) The client receives and stores the session ID. (This works and no duplicates are sent here)
4.) The client sends a request to the lobby system on the server to create a match. (This works and is received correctly)
5.) The server receives the match creation requests, creates the match and sends the match data back to the client (One message is actually sent but the client receives hundreds of the same message (all messages are the same size and contain the same info)).
I have reviewed my lobby system logic and there is no loop that could be sending the match creation reply multiple times, furthermore I know that the "Send" method on the server is only being called once.
I have looked through the websocket-sharp documentation, I thought maybe somehow there were hundreds of sessions being made from one connection or some non-sense along those lines but I am connecting one client and only one session exits :/
Let me know if you have any ideas how this could be happening. Thanks in advance.
See below for code.
Server:
Send Method:
public void Send (string path, string targetID, string script, string method, params object[] data) {
print ("SERVER: Sending Message");
WebSocketServiceHost host = null;
GetSocketServer ().WebSocketServices.TryGetServiceHost (path, out host);
if (host != null) {
Network.Packet packet = new Network.Packet ("Server", targetID, script, method, data);
if (targetID != "Broadcast") {
GetSocketServer ().WebSocketServices.Broadcast (Formatter.singleton.Serialize (packet));
} else if (targetID == "Service") {
host.Sessions.Broadcast (Formatter.singleton.Serialize (packet));
} else {
host.Sessions.SendToAsync (Formatter.singleton.Serialize (packet), targetID);
}
}
}
Client:
Receive Methods:
GetPersistent ().OnMessage += MessageHandler;
void MessageHandler (object sender, MessageEventArgs e) {
Debug.Log ("CLIENT: Message Recieved");
Network.singleton.Recieve (e.RawData);
}
Network: (Used by both Server and Client)
Receive Methods:
public void Recieve (byte[] data) {
object obj = Formatter.singleton.Deserialize (data);
messages.Add (messages.Count, obj);
}
IEnumerator ProcessorCoro () {
WaitForSeconds delay = new WaitForSeconds (Time.deltaTime);
while (true) {
if (messages.Count >= 1) {
Process (messages [(messages.Count - 1)]);
messages.Remove ((messages.Count - 1));
}
yield return delay;
}
}
public void Process (object data) {
Network.Packet packet = (Network.Packet)data;
switch (packet.script) {
case "Home":
Home.singleton.SendMessage (packet.method, data, SendMessageOptions.DontRequireReceiver);
break;
case "Arena":
Arena.singleton.SendMessage (packet.method, data, SendMessageOptions.DontRequireReceiver);
break;
case "Client":
Client.singleton.SendMessage (packet.method, data, SendMessageOptions.DontRequireReceiver);
break;
case "Database":
Database.singleton.SendMessage (packet.method, data, SendMessageOptions.DontRequireReceiver);
break;
}
}
At the client side, you need to ensure that you call the following line only once
GetPersistent ().OnMessage += MessageHandler;
Otherwise, you would be registering the same handler multiple times to the message reception.
Note: This behavior could be desired in case you want to attach multiple handlers to the same OnMessage event.

Timing control in C# Socket Programming

I'm currently getting started on a socket programming project for a University network planning course. I'm also doing a Programming class in which we are learning C# so I thought it appropriate to use C# to complete this assignment.
The assignment is to create a simple Server-Client connection and have data sent between them. That is not too much of a problem, I've read a few tutorials and watched a few videos and I think I know what I'm doing. That part which has me a little confused is this:
"2) Every second, the server sends Client a command to seek measurement data, e.g., through a single letter "R" or "r" (request). (timing control is required here)."
This has me confused, What exactly is timing control? And how can I go about implementing it.
Thanks in advance.
EDIT: I found an "example" of timing control, but it is in the C/C++, Do I need to do something liek this?
/* Step 5.2: Send and Receive Data in loops */
time_old = getTime();
iterationStep = 1;
for (;;)
{
recvStatus = recv(TCPClient, recvBuffer,128,0);
if(recvStatus == 0)
break;
else if(recvStatus == SOCKET_ERROR)
{
printf("Failed in recv(): %d\n",WSAGetLastError());
break;
}
recvBuffer[recvStatus] = 0x00; /* '\0' */
time_new = getTime();
time_interval = time_new - time_old;
time_old = time_new;
printf("Step = %5d; Time Interval = %8.6f; Received String: %s\n", iterationStep,time_interval,recvBuffer);
iterationStep++;
}
/* if "EXIT" received, terminate the program */
if (!strcmp(recvBuffer,"EXIT"))
{
printf("TCP Server ready to terminate.");
break;
}
}
EDIT 2:
Im trying now to use this method but am having some trouble. I have created this method:
private static void SendRequest(Object source, ElapsedEventArgs e) {
byte[] buffer = Encoding.Default.GetBytes("WAAAAT");
acc.Send(buffer, 0, buffer.Length, 0);
}
But as you can see, I cannot use the "acc" socket because I can set it as a parameter. I tried to but then I get a lot of errors when calling the method, any advice?
It sounds like you will need to use the "System.Timers.Timer" class to execute your "send request" function every second.
Example:
static void Main()
{
// Create a timer with a one second interval.
aTimer = new System.Timers.Timer(1000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += SendRequest;
aTimer.Enabled = true;
}
private static void SendRequest(Object source, ElapsedEventArgs e)
{
// maybe end existing request if not completed?
// send next request
}
Whether you time out(cancel) any existing requests before starting a new one will depend on your requirements as it is also possible to have many requests running in parallel. If you do need to kill a request, you can do so by disposing the System.Net.Sockets.Socket that initiated the connection attempt (you will need to handle any errors thrown by the Socket.Connect).
Timing control sounds like a mechanism to insure that the requests are fired 1 sec apart and that if a request doesn't complete in a timely fashion to terminate that request and fire the next one.
Take a scenario
Request 1 fires at point 0
After 1 sec request 1 hasn't received an answer but request 2 needs to fire.
You probably need to implement a timeout system based on a clock.

What is better approach to listen in MultiThreading Service?

I am relatively new both to MSMQ and Threading in .NET. I have to create a service which listen in different threads, via TCP and SNMP, several network Devices and all this stuff run in dedicated threads, but here also is required to listen on MSMQ Queue from another applications.
I am analyzing another similar projects and there is used next logic:
private void MSMQRetrievalProc()
{
try
{
Message mes;
WaitHandle[] handles = new WaitHandle[1] { exitEvent };
while (!exitEvent.WaitOne(0, false))
{
try
{
mes = MyQueue.Receive(new TimeSpan(0, 0, 1));
HandleMessage(mes);
}
catch (MessageQueueException)
{
}
}
}
catch (Exception Ex)
{
//Handle Ex
}
}
MSMQRetrievalThread = new Thread(MSMQRetrievalProc);
MSMQRetrievalThread.Start();
But in another service (message dispatcher) I used asynchronous messages' reading based on MSDN Example:
public RootClass() //constructor of Main Class
{
MyQ = CreateQ(#".\Private$\MyQ"); //Get or create MSMQ Queue
// Add an event handler for the ReceiveCompleted event.
MyQ.ReceiveCompleted += new
ReceiveCompletedEventHandler(MsgReceiveCompleted);
// Begin the asynchronous receive operation.
MyQ.BeginReceive();
}
private void MsgReceiveCompleted(Object source, ReceiveCompletedEventArgs asyncResult)
{
try
{
// Connect to the queue.
MessageQueue mq = (MessageQueue)source;
// End the asynchronous Receive operation.
Message m = mq.EndReceive(asyncResult.AsyncResult);
// Process received message
// Restart the asynchronous Receive operation.
mq.BeginReceive();
}
catch (MessageQueueException Ex)
{
// Handle sources of MessageQueueException.
}
return;
}
Does asynchronous handling suppose that every message will be handled in other than main thread?
Could and need this (2nd) approach be put in separate thread?
Please advice better approach or some simple alternatives.
Messages arrival in Queue doesn't have some rule-defined behavior. It may be that for long time no nay message will arrive or in one second there my arrive many (up to 10 or even more) messages. Based on actions defined in some message it will need to delete/change some objects having running threads.
I highly recommend using WCF for MSMQ.
http://msdn.microsoft.com/en-us/library/ms789048.aspx
This allows you to both asynchronous handle the incoming calls using the WCF threading model which allows for throttling, capping, retries, etc...

Categories

Resources