BlockingCollection having issues with byte arrays - c#

I am having an issue where an object with a byte[20] is being passed into a BlockingCollection on one thread and another thread returning the object with a byte[0] using BlockingCollection.Take(). I think this is a threading issue but I do not know where or why this is happening considering that BlockingCollection is a concurrent collection.
Sometimes on thread2, myclass2.mybytes equals byte[0]. Any information on how to fix this is greatly appreciated.
[EDIT] The original code.
I removed the above code that seemed to run just fine so I took the time to go through my original code and post it.
MessageBuffer.cs
public class MessageBuffer : BlockingCollection<Message>
{
}
In the class that has Listener() and ReceivedMessageHandler(object messageProcessor)
private MessageBuffer RecievedMessageBuffer;
On Thread1
private void Listener()
{
while (this.IsListening)
{
try
{
Message message = Message.ReadMessage(this.Stream, this);
if (message != null)
{
this.RecievedMessageBuffer.Add(message);
}
}
catch (IOException ex)
{
if (!this.Client.Connected)
{
this.OnDisconnected();
}
else
{
Logger.LogException(ex.ToString());
this.OnDisconnected();
}
}
catch (Exception ex)
{
Logger.LogException(ex.ToString());
this.OnDisconnected();
}
}
}
Message.ReadMessage(NetworkStream stream, iTcpConnectClient client)
public static Message ReadMessage(NetworkStream stream, iTcpConnectClient client)
{
int ClassType = -1;
Message message = null;
try
{
ClassType = stream.ReadByte();
if (ClassType == -1)
{
return null;
}
if (!Message.IDTOCLASS.ContainsKey((byte)ClassType))
{
throw new IOException("Class type not found");
}
message = Message.GetNewMessage((byte)ClassType);
message.Client = client;
message.ReadData(stream);
if (message.Buffer.Length < message.MessageSize + Message.HeaderSize)
{
return null;
}
}
catch (IOException ex)
{
Logger.LogException(ex.ToString());
throw ex;
}
catch (Exception ex)
{
Logger.LogException(ex.ToString());
//throw ex;
}
return message;
}
On Thread2
private void ReceivedMessageHandler(object messageProcessor)
{
if (messageProcessor != null)
{
while (this.IsListening)
{
Message message = this.RecievedMessageBuffer.Take();
message.Reconstruct();
message.HandleMessage(messageProcessor);
}
}
else
{
while (this.IsListening)
{
Message message = this.RecievedMessageBuffer.Take();
message.Reconstruct();
message.HandleMessage();
}
}
}
PlayerStateMessage.cs
public class PlayerStateMessage : Message
{
public GameObject PlayerState;
public override int MessageSize
{
get { return 12; }
}
public PlayerStateMessage()
: base()
{
this.PlayerState = new GameObject();
}
public PlayerStateMessage(GameObject playerState)
{
this.PlayerState = playerState;
}
public override void Reconstruct()
{
this.PlayerState.Poisiton = this.GetVector2FromBuffer(0);
this.PlayerState.Rotation = this.GetFloatFromBuffer(8);
base.Reconstruct();
}
public override void Deconstruct()
{
this.CreateBuffer();
this.AddToBuffer(this.PlayerState.Poisiton, 0);
this.AddToBuffer(this.PlayerState.Rotation, 8);
base.Deconstruct();
}
public override void HandleMessage(object messageProcessor)
{
((MessageProcessor)messageProcessor).ProcessPlayerStateMessage(this);
}
}
Message.GetVector2FromBuffer(int bufferlocation)
This is where the exception is thrown because this.Buffer is byte[0] when it should be byte[20].
public Vector2 GetVector2FromBuffer(int bufferlocation)
{
return new Vector2(
BitConverter.ToSingle(this.Buffer, Message.HeaderSize + bufferlocation),
BitConverter.ToSingle(this.Buffer, Message.HeaderSize + bufferlocation + 4));
}

So this was a hard problem to solve. As far as I know, I was just receiving random bytes so I changed up my "Message" quite a bit. there is now a header buffer and a data buffer. The entire message is encapsulated with a beginning marker and an ending marker while the header and data buffers are each encapsulated by different markers. this has allowed me to tell when I have received bad data and can discard the message. If the message does get discarded, on the next message read, instead of just checking if the first 4 bytes received is the opening marker, it will read byte by byte until the last 4 bytes read are equal to the marker.

Related

Socket using. Data is not sending on the second time

Issue description.
I sending and receiving data. When i launch program, data who i send and receive, displayed is right. If relaunch program in 1 minutes, no more, data send and receive displayed is currect.
BUT! IF i relaunching program more then after 2 minutes, FIRST receiving and sending displayed is right, BUT SECOND sending and receiving data, is not displayed (((
What's happening, and how i fix this???
Thanks for any help!
public override bool Connect()
{
try
{
if (NetClient != null)
{
NetClient.Close();
}
NetClient = new Socket(ConnectionPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = NetClient.BeginConnect(ConnectionPoint, null, null);
bool success = result.AsyncWaitHandle.WaitOne(connectionDelay, false/*true*/);
if (NetClient.Connected)
{
Log("report.log", string.Format("Connection OK"));
return true;
}
Log("report.log", string.Format("NetClient is not connected"));
}
catch (Exception e)
{
MessageBox.Show(e.Message);
Log("report.log", string.Format("NetClient error while connecting: {0}", e.Message));
}
return false;
}
public override bool Send(byte[] data)
{
try
{
if (NetClient.Connected)
{
NetClient.SendTo(data, ConnectionPoint);
Thread.Sleep(transferDelay);
return true;
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
return false;
}
public override string Receive(int length)
{
byte[] data = new byte[bufferSize]; // bufferSize = i tryed any buffer from 5 bytes to 16384 bytes
string strbuff = "";
try
{
if (NetClient.Connected)
{
do
{
IAsyncResult result = NetClient.BeginReceive(data, 0, bufferSize, SocketFlags.None, null, null);
bool success = result.AsyncWaitHandle.WaitOne(connectionDelay, true);
int receivedBytesCount = NetClient.EndReceive(result);
if (receivedBytesCount == 0)
{
receivedBytesCount = 0;
}
strbuff += Encoding.ASCII.GetString(data, 0, receivedBytesCount);
} while (NetClient.Available > 0);
if (NetClient != null && NetClient.Connected)
{
NetClient.Shutdown(SocketShutdown.Both);
NetClient.Close();
}
return strbuff;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return null;
}
public override void Disconnect()
{
try
{
if (NetClient.Connected)
{
NetClient.Shutdown(SocketShutdown.Both);
NetClient.Close();
}
else
{
if (NetClient != null)
{
NetClient.Close();
}
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}

How to clean the queue from all of the processed items?

There is a global queue of objects that you have to send to your customers. Queue is continually filled with new elements in its flow (one element in a second), that`s why you have to send constantly. Every client is served in a separate thread. After the object is sent to all clients it must be removed from the queue. It seems to be easy, but how to know that all the threads have already sent a particular object?
I do everything on the socket.
Thread threadForClientSending = new Thread(delegate()
{
while (true)
{
try
{
List<SymbolsTable> [] localArrayList ;
//main.que -- global queue
foreach (var eachlist in localArrayList = main.que.ToArray())
{
foreach (var item in eachlist)
{
byte[] message =
encoding.GetBytes((item.GetHashCode()%100).ToString() + " "+item.SDate +"\n\r");
client.Send(message);
}
Thread.Sleep(500);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
break;
}
}
});
Such code sends everything to everyone, but it doesn`t clean the queue.
How to clean the queue from all of the processed items?
public static ConcurrentQueue<List<SymbolsTable>> que = new ConcurrentQueue<List<SymbolsTable>>();
public partial class SymbolsTable
{
public string SName { get; set; }
public Nullable<double> SPrice { get; set; }
public Nullable<int> SVolume { get; set; }
public System.DateTime SDate { get; set; }
}
NOTE: I highly recommend to define local queue for each client (task in server) to achieve maximum concurrency and cleaner code.
You can achieve what you need by using a CountDownEvent which would hold thread access for each item, We should set it to number of available worker that send data to clients.
here is how we can do it:
Definitions:
public static ConcurrentQueue<List<SymbolsTable>> que = new ConcurrentQueue<List<SymbolsTable>>();
public static CountdownEvent counter = new CountdownEvent(NumberOfThreads);
private const int NumberOfThreads = 3; //for example we have 3 clients here
Thread:
Thread threadForClientSending = new Thread(delegate()
{
while (true)
{
try
{
List<SymbolsTable> list;
var peek = que.TryPeek(out list);
if (!peek)
{
Thread.Sleep(100); //nothing to pull
continue;
}
foreach (var item in list)
{
main.que -- global queue
byte[] message =
encoding.GetBytes((item.GetHashCode() % 100).ToString() + " " + item.SDate + "\n\r");
client.Send(message);
Thread.Sleep(500);
}
counter.Signal(); //the thread would signal itself as finished, and wait for others to finish the task
lock (que)
{
List<SymbolsTable> lastList;
if (que.TryPeek(out lastList) && lastList.Equals(list))
{
//just one of the threads would dequeue the item
que.TryDequeue(out lastList);
counter.Reset(); //reset counter for next iteration
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
break;
}
}
});
here we used TryPeek to just access the item in queue so we won't remove it, at the end in:
lock (que)
{
List<SymbolsTable> lastList;
if (que.TryPeek(out lastList) && lastList.Equals(list))
{
//just one of the threads would dequeue the item
que.TryDequeue(out lastList);
counter.Reset(); //reset counter for next iteration
}
}
we would lock the que so only one thread at a time can access it, then we check to see if the processed item has been removed from queue and if not we will remove it here.
More Elegant Solution (in my Humble Opinion):
as you saw in previous solution we're blocking threads to finish the task for each item together,adding a local queue to each thread would remove this blocking mechanism, so we can achieve maximum concurrency.
I suggest something like:
class GlobalQueue
{
private readonly List<IMyTask> _subscribers=new List<IMyTask>();
public void Subscribe(IMyTask task)
{
_subscribers.Add(task);
}
public void Unsubscribe(IMyTask task)
{
_subscribers.Remove(task);
}
public void Enqueue(List<SymbolsTable> table)
{
foreach (var s in _subscribers)
s.Enqueue(table);
}
}
interface IMyTask
{
void Enqueue(List<SymbolsTable> table);
}
which your task would be roughly like:
class MyTask : IMyTask
{
private readonly ConcurrentQueue<List<SymbolsTable>> _localQueue = new ConcurrentQueue<List<SymbolsTable>>();
private readonly Thread _thread;
private bool _started;
public void Enqueue(List<SymbolsTable> table)
{
_localQueue.Enqueue(table);
}
public MyTask()
{
_thread = new Thread(Execute);
}
public void Start()
{
_started = true;
_thread.Start();
}
public void Stop()
{
_started = false;
}
private void Execute()
{
while (_started)
{
try
{
List<SymbolsTable> list;
var peek = _localQueue.TryDequeue(out list);
if (!peek)
{
Thread.Sleep(100); //nothing to pull
continue;
}
foreach (var item in list)
{
byte[] message =
encoding.GetBytes((item.GetHashCode() % 100).ToString() + " " + item.SDate + "\n\r");
client.Send(message);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
break;
}
}
}
}

Receive JSON from a MS Message queue

I have some trouble reading Json formatted message from a MS queue.
I am able to connect to the queue and read the first message but when trying to access the Body property the value is null.
Also when trying to read from the body stream I have also an error message saying the stream was not readable.
The queue is transactional but I don't think this is relevant here.
private readonly MessageQueue _queue;
private bool _listen;
private Func<object, bool> _messageHandler;
public Listener(string queuePath)
{
_queue = new MessageQueue(queuePath);
}
public void Start(Func<object, bool> messageHandler)
{
_listen = true;
_queue.PeekCompleted += OnPeekCompleted;
_messageHandler = messageHandler;
StartListening();
}
private void StartListening()
{
if (!_listen)
{
return;
}
try
{
_queue.BeginPeek();
}
catch (Exception ex)
{
Console.WriteLine("An exception occurred when peeking");
}
}
private void OnPeekCompleted(object sender, PeekCompletedEventArgs e)
{
_queue.EndPeek(e.AsyncResult);
var messageId = string.Empty;
using (var transaction = new MessageQueueTransaction())
{
transaction.Begin();
try
{
using (var message = _queue.Receive(transaction))
{
if (!_listen || message == null)
{
return;
}
messageId = message.Id;
if (ProcessMessage(message))
{
transaction.Commit();
}
else
{
transaction.Abort();
}
}
}
catch (Exception exception)
{
transaction.Abort();
}
}
StartListening();
}
Is there something special to do when sending json via MSMQ to retrieve message body ?
Many thanks

Asynchronous HttpListener has each request is received twice

I have implemented an asynchronous http listener in c#.
I followed the tutorial provided here by Microsoft
and found another tutorial which i stupidly not bookmarked and now can't find again. Meaning that I have some code that I would not have written that way myself but the explanations provided made sense so I followed that.
Now I am facing two problems:
First, I have to restart the listener after each request with Listener.Stop() and then call the StartListening method and again and second, when I do this, I receive each request twice.
The request does net get sent twice, but I receive it twice.
It does not however get received twice when I pause the Thread I am listening on for about 2 seconds.
I am sorry if I am quite vague in my explanations, but so is my understanding of my problem, I have no idea what is causing it.
Since the callback method is where most of the stuff happens, I will just post it, please tell me if you need any more code.
Any help will be gladly appreciated, since I am really stuck on this one.
public void ListenAsynchronously()
{
if (listener.Prefixes.Count == 0) foreach (string s in prefixes) listener.Prefixes.Add(s);
try
{
listener.Start();
}
catch (Exception e)
{
Logging.logException(e);
}
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(Listen));
}
private void Listen(object state)
{
while (listener.IsListening)
{
listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);
listenForNextRequest.WaitOne();
}
}
private void ListenerCallback(IAsyncResult ar)
{
HttpListener httplistener = ar.AsyncState as System.Net.HttpListener;
System.Net.HttpListenerContext context = null;
int requestNumber = System.Threading.Interlocked.Increment(ref requestCounter);
if (httplistener == null) return;
try
{
context = httplistener.EndGetContext(ar);
}
catch(Exception ex)
{
return;
}
finally
{
listenForNextRequest.Set();
}
if (context == null) return;
System.Net.HttpListenerRequest request = context.Request;
if (request.HasEntityBody)
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(request.InputStream, request.ContentEncoding))
{
string requestData = sr.ReadToEnd();
//Stuff I do with the request happens here
}
}
try
{
using (System.Net.HttpListenerResponse response = context.Response)
{
//response stuff happens here
}
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.LongLength;
response.OutputStream.Write(buffer, 0, buffer.Length);
response.Close();
StopListening();
//If I dont set the thread to sleep here, I receive the double requests
System.Threading.Thread.Sleep(2500);
ListenAsynchronously();
}
}
catch (Exception e)
{
}
}
I am not sure why you are calling StopListening() and ListenAsynchronously() in your ListenerCallback() method. The Listen() method is being run in a thread and will continue to get each next incoming request. If I was writing this, I would not be using a instance variable of HttpListener. Create a new one in your ListenAsynchronously method and pass it in your state object, for example,
public class HttpListenerCallbackState
{
private readonly HttpListener _listener;
private readonly AutoResetEvent _listenForNextRequest;
public HttpListenerCallbackState(HttpListener listener)
{
if (listener == null) throw new ArgumentNullException("listener");
_listener = listener;
_listenForNextRequest = new AutoResetEvent(false);
}
public HttpListener Listener { get { return _listener; } }
public AutoResetEvent ListenForNextRequest { get { return _listenForNextRequest; } }
}
public class HttpRequestHandler
{
private int requestCounter = 0;
private ManualResetEvent stopEvent = new ManualResetEvent(false);
public void ListenAsynchronously(IEnumerable<string> prefixes)
{
HttpListener listener = new HttpListener();
foreach (string s in prefixes)
{
listener.Prefixes.Add(s);
}
listener.Start();
HttpListenerCallbackState state = new HttpListenerCallbackState(listener);
ThreadPool.QueueUserWorkItem(Listen, state);
}
public void StopListening()
{
stopEvent.Set();
}
private void Listen(object state)
{
HttpListenerCallbackState callbackState = (HttpListenerCallbackState)state;
while (callbackState.Listener.IsListening)
{
callbackState.Listener.BeginGetContext(new AsyncCallback(ListenerCallback), callbackState);
int n = WaitHandle.WaitAny(new WaitHandle[] { callbackState.ListenForNextRequest, stopEvent});
if (n == 1)
{
// stopEvent was signalled
callbackState.Listener.Stop();
break;
}
}
}
private void ListenerCallback(IAsyncResult ar)
{
HttpListenerCallbackState callbackState = (HttpListenerCallbackState)ar.AsyncState;
HttpListenerContext context = null;
int requestNumber = Interlocked.Increment(ref requestCounter);
try
{
context = callbackState.Listener.EndGetContext(ar);
}
catch (Exception ex)
{
return;
}
finally
{
callbackState.ListenForNextRequest.Set();
}
if (context == null) return;
HttpListenerRequest request = context.Request;
if (request.HasEntityBody)
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(request.InputStream, request.ContentEncoding))
{
string requestData = sr.ReadToEnd();
//Stuff I do with the request happens here
}
}
try
{
using (HttpListenerResponse response = context.Response)
{
//response stuff happens here
string responseString = "Ok";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.LongLength;
response.OutputStream.Write(buffer, 0, buffer.Length);
response.Close();
}
}
catch (Exception e)
{
}
}
}

Asynchronous socket, forced disconnection and reuse

Im writing an application which is going to act as a tcp listener for a single client. The client is a java applet and will periodically connect to the listener, send some data and then wait for a response.
The code for the TcpServer class below has been largely lifted from an example provided by a more knowledgeable stackoverflow member in response to a different question.
Everything was going great until I found something in testing which wasnt mentioned in any of the interface documents I have. After the server has responded to the client it must then disconnect the client and start listening again.
My first thought was to call Disconnect() from inside SendData() but this results in a call to ReceiveCompleted() from somewhere and a nasty exception about the socket already being disposed.
Is this requirement easily achievable with the code design I have, and will I run into any problems in reusing the socket for subsequent connections?
sealed class TcpServer : IDisposable
{
#region Fields
private const int SocketBufferSize = 1024;
private readonly TcpListener tcpListener;
private Socket connectedSocket;
private bool disposed = false;
#endregion Fields
#region Constructors
public TcpServer(int port)
{
tcpListener = new TcpListener(IPAddress.Any, port);
tcpListener.Start();
tcpListener.BeginAcceptSocket(EndAcceptSocket, tcpListener);
}
~TcpServer()
{
Dispose(false);
}
#endregion Constructors
#region Events
public event EventHandler<DataReceivedEventArgs> DataReceived;
public event EventHandler<IPEndPointEventArgs> SocketConnected;
public event EventHandler<IPEndPointEventArgs> SocketDisconnected;
#endregion Events
#region Methods
public void Dispose()
{
Dispose(true);
}
public void SendData(byte[] data)
{
if (connectedSocket == null)
{
return;
}
connectedSocket.Send(data);
}
private void BeginReceiveAsync(Socket sock, SocketAsyncEventArgs e)
{
if (!sock.ReceiveAsync(e))
{
ReceiveCompleted(sock, e);
}
}
private void Connected(Socket socket)
{
var endPoint = (IPEndPoint)socket.RemoteEndPoint;
connectedSocket = socket;
OnSocketConnected(endPoint);
}
private void Disconnect(Socket socket)
{
var endPoint = (IPEndPoint)socket.RemoteEndPoint;
socket.Close();
connectedSocket = null;
OnSocketDisconnected(endPoint);
tcpListener.BeginAcceptSocket(EndAcceptSocket, tcpListener);
}
private void Dispose(bool disposing)
{
if (this.disposed == false)
{
if (disposing)
{
try
{
if (tcpListener != null)
{
this.disposed = true;
tcpListener.Stop();
}
}
catch (Exception ex)
{
TraceLog.Error("TcpServer: tcpListener.Stop(): {0}", ex.Message);
}
try
{
if (connectedSocket != null)
{
connectedSocket.Close();
connectedSocket = null;
}
}
catch (SocketException ex)
{
TraceLog.Error("TcpServer: connectedSocket.Close(): {0}", ex);
}
}
this.disposed = true;
}
}
private void EndAcceptSocket(IAsyncResult asyncResult)
{
var listener = (TcpListener)asyncResult.AsyncState;
if (disposed)
{
return;
}
try
{
Socket sock = listener.EndAcceptSocket(asyncResult);
Connected(sock);
var e = new SocketAsyncEventArgs();
e.Completed += ReceiveCompleted;
e.SetBuffer(new byte[SocketBufferSize], 0, SocketBufferSize);
BeginReceiveAsync(sock, e);
}
catch (SocketException ex)
{
TraceLog.Error("TcpServer.EndAcceptSocket: {0}", ex.Message);
}
catch (Exception ex)
{
TraceLog.Error("TcpServer.EndAcceptSocket: {0}", ex.Message);
}
}
private void OnDataReceived(byte[] data, IPEndPoint ipEndPoint)
{
if (DataReceived != null)
{
DataReceived(this, new DataReceivedEventArgs(data, ipEndPoint));
}
}
private void OnSocketConnected(IPEndPoint ipEndPoint)
{
if (SocketConnected != null)
{
SocketConnected(this, new IPEndPointEventArgs(ipEndPoint));
}
}
private void OnSocketDisconnected(IPEndPoint ipEndPoint)
{
if (SocketDisconnected != null)
{
SocketDisconnected(this, new IPEndPointEventArgs(ipEndPoint));
}
}
private void ReceiveCompleted(object sender, SocketAsyncEventArgs e)
{
var sock = (Socket)sender;
if (!sock.Connected)
{
Disconnect(sock);
}
try
{
int size = e.BytesTransferred;
if (size == 0)
{
Disconnect(sock);
}
else
{
var buf = new byte[size];
Array.Copy(e.Buffer, buf, size);
ReceiveData(buf, (IPEndPoint)sock.RemoteEndPoint);
BeginReceiveAsync(sock, e);
}
}
catch (SocketException ex)
{
TraceLog.Error("TcpServer: ReceiveCompleted: {0}", ex.Message);
}
catch (Exception ex)
{
TraceLog.Error("TcpServer: ReceiveCompleted: {0}", ex.Message);
}
}
private void ReceiveData(byte[] data, IPEndPoint endPoint)
{
OnDataReceived(data, endPoint);
}
#endregion Methods
}
Whenever I'm writing code that wraps around System.Net.Sockets.Socket, I find myself constantly adding try/catch clauses for SocketException and ObjectDisposedException. In most cases, ObjectDisposedException can simply be ignored, as it, in 99% of cases, indicates that the client has simply disconnected.
At least that's my impression of how the Socket API in .NET works. Try adding some exception handlers here and there, and see how it goes. In any case, your Disconnect method should not do more than something like this:
public void Disconnect()
{
try
{
connectedSocket.Shutdown(SocketShutdown.Both);
}
catch (Exception)
{
// Ignore the exception. The client probably already disconnected.
}
connectedSocket.Dispose(); // This is safe; a double dispose will simply be ignored.
}
I hope that sheds some light on the issue...

Categories

Resources