I'm writing a program which listens to an incoming TcpClient and handles data when it arrives. The Listen() method is run on a separate thread within the component, so it needs to be threadsafe. If I break out of a do while loop while I'm within a lock() statement, will the lock be released? If not, how do I accomplish this?
Thanks!
(Any other advice on the subject of Asynchronous TCP Sockets is welcome as well.)
private void Listen()
{
do
{
lock (_clientLock)
{
if (!_client.Connected) break;
lock (_stateLock)
{
if (!_listening) break;
if (_client.GetStream().DataAvailable) HandleData();
}
}
Thread.Sleep(0);
} while (true);
}
Yes. The lock statement translates into a try/finally clause. In C# 4, for example, a lock statement like so:
lock(obj)
{
// body
}
roughly translates (taken from Eric Lippert's blog here) to:
bool lockWasTaken = false;
var temp = obj;
try
{
Monitor.Enter(temp, ref lockWasTaken);
{
// body
}
}
finally
{
if (lockWasTaken)
Monitor.Exit(temp);
}
When the execution leaves the scope of the lock {}, the underlying lock will be released automatically. This will happen no matter how you exit scope (break/return/etc), since the call to Monitor.Exit is wrapped, internally, inside of the finally block of a try/finally.
Yes, the lock will be released. You can use ILDASM or Reflector to look at the actual generated code. The lock statement is shorthand for the following code (roughly).
Monitor.Enter(_client);
try
{
// do your stuff
}
finally {
Monitor.Exit(_client);
}
Notice the finally block is always executed.
Because you asked for other advice...I noticed that you are nesting locks. This, by itself, is not necessarily a bad thing. But, it is one my red flags I watch out for. There is the possibility of a deadlock if you ever acquire those two locks in a different order in another part of your code. I am not saying there is anything wrong with your code. It is just something else to watch out for because it is easy to get wrong.
Once you exit the lock{}, it will unlock what you have locked (it's just like a using statement in that regard). It doesn't matter where you exit (the beginning, the end, or the middle), it's that you left the scope of the lock at all. Think about what would happen if you raised an exception in the middle.
To answer the other half of your question:
Any other advice on the subject of Asynchronous TCP Sockets is welcome as well
Simply put I wouldn't manage this in the fashion demonstrated by your original post. Rather seek help from the System.Net.Sockets.TcpClient and the System.Net.Sockets.TcpListener classes. Use the async calls like BeginAcceptSocket(...) and BeginRead(...) and allow the ThreadPool to do it's job. It's really pretty easy to put together that way.
You should be able to achieve all the server behavior you desire without ever coding the dreaded words "new Thread" :)
Here is a basic example of the idea, minus the idea of graceful shutdown, exception handling ect:
public static void Main()
{
TcpListener listener = new TcpListener(new IPEndPoint(IPAddress.Loopback, 8080));
listener.Start();
listener.BeginAcceptTcpClient(OnConnect, listener);
Console.WriteLine("Press any key to quit...");
Console.ReadKey();
}
static void OnConnect(IAsyncResult ar)
{
TcpListener listener = (TcpListener)ar.AsyncState;
new TcpReader(listener.EndAcceptTcpClient(ar));
listener.BeginAcceptTcpClient(OnConnect, listener);
}
class TcpReader
{
string respose = "HTTP 1.1 200\r\nContent-Length:12\r\n\r\nHello World!";
TcpClient client;
NetworkStream socket;
byte[] buffer;
public TcpReader(TcpClient client)
{
this.client = client;
socket = client.GetStream();
buffer = new byte[1024];
socket.BeginRead(buffer, 0, 1024, OnRead, socket);
}
void OnRead(IAsyncResult ar)
{
int nBytes = socket.EndRead(ar);
if (nBytes > 0)
{
//you have data... do something with it, http example
socket.BeginWrite(
Encoding.ASCII.GetBytes(respose), 0, respose.Length, null, null);
socket.BeginRead(buffer, 0, 1024, OnRead, socket);
}
else
socket.Close();
}
}
For a much more complicated example of how to do this see the SslTunnel Library I wrote a while ago.
Related
I have single socket, which is blocked on sending the frame and I would like to dispose poller ( and everything related to it ). However, I cannot do it -- calling dispose on socket throws an exception, and calling dispose on poller completely blocks.
Please note, I am using SendFrame and I could use TrySendFrame, but the purpose of this example is to actually block the socket and find a way how to clean up everything.
Example:
private Program()
{
const string address = "tcp://localhost:5000";
var socket = new DealerSocket();
socket.Options.SendHighWatermark = 1;
socket.Options.Identity = Encoding.ASCII.GetBytes(Guid.NewGuid().ToString("N"));
socket.Connect(address);
var poller = new NetMQPoller();
poller.Add(socket);
socket.SendReady += OnSendReady;
poller.RunAsync();
Thread.Sleep(5000);
Console.WriteLine("Disposing");
poller.Dispose(); // get stuck on this one
Console.WriteLine("Disposed");
}
private void OnSendReady(object sender, NetMQSocketEventArgs e)
{
Console.WriteLine("0");
e.Socket.SendFrame("hello");
Console.WriteLine("1");
e.Socket.SendFrame("hello"); // this will block
Console.WriteLine("2");
}
Tested with NetMQ 3.3.3.4 (my primary version for now) and 4.0.0.1.
1) Always zeroize ZMQ_LINGER. Always. Right upon a socket instantiation, so as to prevent otherwise inadvertent blocking on graceful termination { .close() | .term() } operations ( be it a controlled or un-controlled activation of termination ops ( as you already have faced it ) ).
2) Avoid blocking designs. Principally. Each blocking state creates a state, in which all your code is out-of-control. Got it?
I'm trying to use ManualResetEvent to make a semaphore-like situation and I have placed WaitOne, Set and Reset in their right places. The WaitOne instruction is called in a listener thread and is places right after a tcp reading:
var networkStream = _clientSocket.GetStream();
networkStream.Read(bytesFrom, 0, Convert.ToInt32(_clientSocket.ReceiveBufferSize));
_mainthreadControl.WaitOne(Timeout.Infinite);
And Set and Reset instructions are called in another thread, so the socket won't get competed over:
try
{
//some code
_mainthreadControl.Reset();
//some code that uses the same socket as above
_mainthreadControl.Set();
}
catch (Exception ex)
{
//ignored
}
But I need the code to stop when it reaches Reset, and only continue after the WaitOne is reached (and executed), so the code below Reset only runs after the competing thread is waiting.
I don't know if I was clear enough, so I'm glad to add details as needed. Thanks in advance.
If it suites for you. Please try to use additional AutoResetEvent. Like this:
var _additionalControl = new AutoResetEvent(false);
// code gap
var networkStream = _clientSocket.GetStream();
networkStream.Read(bytesFrom, 0, Convert.ToInt32(_clientSocket.ReceiveBufferSize));
_additionalControl.Set();
_mainthreadControl.WaitOne(Timeout.Infinite);
// code gap
try
{
//some code
_mainthreadControl.Reset();
_additionalControl.WaitOne(Timeout.Infinite);
//some code that uses the same socket as above
_mainthreadControl.Set();
}
catch (Exception ex)
{
//ignored
}
In turn I recommend to use System.Threading.Monitor class, cause it's more faster than ManualResetEvent(false), because it's restricted by the single process. If course if you don't need to use lock in another program.
public bool Connect (string address, int remotePort)
{
if (_socket != null && _socket.Connected)
return true;
IPHostEntry hostEntry = Dns.GetHostEntry (address);
foreach (IPAddress ip in hostEntry.AddressList) {
try {
IPEndPoint ipe = new IPEndPoint (ip, remotePort);
_socket = new Socket (ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
_socket.BeginConnect (ipe, new System.AsyncCallback (ConnectionCallback), _socket);
break;
} catch (System.Exception e) {
PushPacket ((ushort)MsgIds.Id.CONNECTION_ATTEMPT_FAILED, e.Message);
return false;
}
}
return true;
}
void ConnectionCallback (System.IAsyncResult ar)
{
NetBitStream stream = new NetBitStream ();
stream._socket = (Socket)ar.AsyncState;
try {
_socket.EndConnect (ar);
_socket.SendTimeout = _sendTimeout;
_socket.ReceiveTimeout = _revTimeout;
PushPacket ((ushort)MsgIds.Id.CONNECTION_REQUEST_ACCEPTED, "");
_socket.BeginReceive (stream.BYTES, 0, NetBitStream.HEADER_LENGTH, SocketFlags.None, new System.AsyncCallback (ReceiveHeader), stream);
} catch (System.Exception e) {
if (e.GetType () == typeof(SocketException)) {
if (((SocketException)e).SocketErrorCode == SocketError.ConnectionRefused) {
PushPacket ((ushort)MsgIds.Id.CONNECTION_ATTEMPT_FAILED, e.Message);
} else
PushPacket ((ushort)MsgIds.Id.CONNECTION_LOST, e.Message);
}
Disconnect (0);
}
}
Here are two functions. When I call
client.Connect ("127.0.0.1", 10001);
It just steps over the break; after
_socket.BeginConnect (ipe, new System.AsyncCallback (ConnectionCallback), _socket);
and goes to return true;. I set a breakpoint at ConnectionCallback but it does not go into this function.
There is no server listening on the 10001 port.
So I think it at least should throw an exception (connect failed), then go into the catch.
Or have I made a mistake in the two functions?
Here is a Minimal, Complete, and Verifiable example
using System;
using System.Net.Sockets;
using System.Net;
namespace TestSocket
{
class MainClass
{
public static void Main (string[] args)
{
NetTCPClient tcp_client = new NetTCPClient ();
tcp_client.Connect ("127.0.0.1", 10001);
}
}
class NetTCPClient
{
Socket _socket = null;
public bool Connect (string address, int remote_port)
{
if (_socket != null && _socket.Connected)
return true;
IPHostEntry host_entry = Dns.GetHostEntry (address);
foreach (IPAddress ip in host_entry.AddressList) {
try {
IPEndPoint ipe = new IPEndPoint (ip, remote_port);
_socket = new Socket (ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult ia = _socket.BeginConnect (ipe, new System.AsyncCallback (ConnectionCallback), _socket);
break;
} catch (Exception e) {
Console.WriteLine ("Connet() catch an exception!");
return false;
}
}
return true;
}
void ConnectionCallback (System.IAsyncResult ar)
{
Console.WriteLine ("ConnectionCallback() ");
}
}
}
The debugger doesn't work that way. With very few exceptions, it will not switch threads without explicit instruction from you.
When you are stepping through the Connect() method you wrote, you are debugging a particular thread in your program. The ConnectionCallback() method, if and when it is called (note that it is not generally going to be called synchronously during your call to BeginConnect()), will be called in a different thread. If you want to debug it, you need to set a breakpoint at or in the ConnectionCallback() method itself.
With a breakpoint set in that method, you are assured that the debugger will pause the execution of your program there, regardless of which thread is executing that method.
EDIT:
Thank you for the full code example. Assuming that is in fact the code example you are testing with and having trouble with, then your problem is (as was already guessed) one of two things:
After stepping through the call to the Connect() method, you do not resume execution of your program. I.e. you did not click the "Continue" button or use the "Continue" menu item in the "Debug" menu. Or…
You do resume execution of your program, which then promptly exits before the connection attempt can be resolved.
In case #1 above, you never see the breakpoint because your program is not executing. The breakpoint can only be triggered if execution of the program does in fact arrive at the breakpoint. But the execution of your program can't arrive there if it's not happening at all.
In case #2 above, you never see the breakpoint because your program is not executing. In this case, it's because the program has exited altogether.
If you want to see the breakpoint at the ConnectionCallback() method get triggered, you need to let the program run, and for long enough for that to happen.
As a quick proof-of-concept, I set a breakpoint at that method, and added this statement to the end of the Main() method:
Thread.Sleep(TimeSpan.FromMinutes(5));
I then used the debugger to step through the Main() method. It of course paused to let the program run at the above statement I'd just added, but then very quickly interrupted the program again, right at the desired breakpoint. (I didn't have to wait anywhere close to 5 minutes…I just used that as a very large time value that I was sure would be enough).
For what it's worth, I also tried a test where I stepped through the original Main(), i.e. without the call to Thread.Sleep(), but waited about 5-10 seconds after stepping over the call to Connect() before proceeding. In that case, at least on my computer, I also did see the breakpoint triggered. That particular test is somewhat dependent on machine configuration, so it's less reliable than adding the call to Thread.Sleep(). But it did work in my case.
I think you may have misunderstood what BeginConnect does. That doesn't make the connection - it just starts making the connection, asynchronously. So yes, I'm not at all surprised that "step over" immediately steps to the next statement - that's working as intended.
However, I would have expected that a breakpoint in ConnectionCallback would be hit - that's what you should concentrate on as a problem. That's also where you should put the exception handling, as that's where any problems with making the connection would be found.
Alternatively, if you're using C# 5 or higher, you should look into using async/await, which would allow you to get rid of all the callbacks. Then you'll get a much more familiar experience when debugging - if you step over that line, it really will be connected (or there'll be a failure) by the time you hit the next line. Just be aware that other things may happen (even on the same thread) while it's "awaiting" the response.
Unfortunately, I can't see anything in Socket which implements the relevant pattern. You could use TaskFactory.FromAsync to adapt the "old" style to the "new" style, but it's likely to be fairly painful.
Another approach is to try to move to higher-level constructs like TcpClient instead of the lower-level Socket class.
I have a client/server infrastructure. At present they use a TcpClient and TcpListener to send a receive data between all the clients and server.
What I currently do is when data is received (on it's own thread), it is put in a queue for another thread to process in order to free the socket so it is ready and open to receive new data.
// Enter the listening loop.
while (true)
{
Debug.WriteLine("Waiting for a connection... ");
// Perform a blocking call to accept requests.
using (client = server.AcceptTcpClient())
{
data = new List<byte>();
// Get a stream object for reading and writing
using (NetworkStream stream = client.GetStream())
{
// Loop to receive all the data sent by the client.
int length;
while ((length = stream.Read(bytes, 0, bytes.Length)) != 0)
{
var copy = new byte[length];
Array.Copy(bytes, 0, copy, 0, length);
data.AddRange(copy);
}
}
}
receivedQueue.Add(data);
}
However I wanted to find out if there is a better way to do this. For example if there are 10 clients and they all want to send data to the server at the same time, one will get through while all the others will fail.Or if one client has a slow connection and hogs the socket all other communication will halt.
Is there not some way to be able to receive data from all clients at the same time and add the received data in the queue for processing when it has finished downloading?
So here is an answer that will get you started - which is more beginner level than my blog post.
.Net has an async pattern that revolves around a Begin* and End* call. For instance - BeginReceive and EndReceive. They nearly always have their non-async counterpart (in this case Receive); and achieve the exact same goal.
The most important thing to remember is that the socket ones do more than just make the call async - they expose something called IOCP (IO Completion Ports, Linux/Mono has these two but I forget the name) which is extremely important to use on a server; the crux of what IOCP does is that your application doesn't consume a thread while it waits for data.
How to Use The Begin/End Pattern
Every Begin* method will have exactly 2 more arguments in comparisson to it's non-async counterpart. The first is an AsyncCallback, the second is an object. What these two mean is, "here is a method to call when you are done" and "here is some data I need inside that method." The method that gets called always has the same signature, inside this method you call the End* counterpart to get what would have been the result if you had done it synchronously. So for example:
private void BeginReceiveBuffer()
{
_socket.BeginReceive(buffer, 0, buffer.Length, BufferEndReceive, buffer);
}
private void EndReceiveBuffer(IAsyncResult state)
{
var buffer = (byte[])state.AsyncState; // This is the last parameter.
var length = _socket.EndReceive(state); // This is the return value of the method call.
DataReceived(buffer, 0, length); // Do something with the data.
}
What happens here is .Net starts waiting for data from the socket, as soon as it gets data it calls EndReceiveBuffer and passes through the 'custom data' (in this case buffer) to it via state.AsyncResult. When you call EndReceive it will give you back the length of the data that was received (or throw an exception if something failed).
Better Pattern for Sockets
This form will give you central error handling - it can be used anywhere where the async pattern wraps a stream-like 'thing' (e.g. TCP arrives in the order it was sent, so it could be seen as a Stream object).
private Socket _socket;
private ArraySegment<byte> _buffer;
public void StartReceive()
{
ReceiveAsyncLoop(null);
}
// Note that this method is not guaranteed (in fact
// unlikely) to remain on a single thread across
// async invocations.
private void ReceiveAsyncLoop(IAsyncResult result)
{
try
{
// This only gets called once - via StartReceive()
if (result != null)
{
int numberOfBytesRead = _socket.EndReceive(result);
if(numberOfBytesRead == 0)
{
OnDisconnected(null); // 'null' being the exception. The client disconnected normally in this case.
return;
}
var newSegment = new ArraySegment<byte>(_buffer.Array, _buffer.Offset, numberOfBytesRead);
// This method needs its own error handling. Don't let it throw exceptions unless you
// want to disconnect the client.
OnDataReceived(newSegment);
}
// Because of this method call, it's as though we are creating a 'while' loop.
// However this is called an async loop, but you can see it the same way.
_socket.BeginReceive(_buffer.Array, _buffer.Offset, _buffer.Count, SocketFlags.None, ReceiveAsyncLoop, null);
}
catch (Exception ex)
{
// Socket error handling here.
}
}
Accepting Multiple Connections
What you generally do is write a class that contains your socket etc. (as well as your async loop) and create one for each client. So for instance:
public class InboundConnection
{
private Socket _socket;
private ArraySegment<byte> _buffer;
public InboundConnection(Socket clientSocket)
{
_socket = clientSocket;
_buffer = new ArraySegment<byte>(new byte[4096], 0, 4096);
StartReceive(); // Start the read async loop.
}
private void StartReceive() ...
private void ReceiveAsyncLoop() ...
private void OnDataReceived() ...
}
Each client connection should be tracked by your server class (so that you can disconnect them cleanly when the server shuts down, as well as search/look them up).
You should use asynchronous socket programming to achieve this. Take a look at the example provided by MSDN.
You should use asynchronous method of reading the data, an example is:
// Enter the listening loop.
while (true)
{
Debug.WriteLine("Waiting for a connection... ");
client = server.AcceptTcpClient();
ThreadPool.QueueUserWorkItem(new WaitCallback(HandleTcp), client);
}
private void HandleTcp(object tcpClientObject)
{
TcpClient client = (TcpClient)tcpClientObject;
// Perform a blocking call to accept requests.
data = new List<byte>();
// Get a stream object for reading and writing
using (NetworkStream stream = client.GetStream())
{
// Loop to receive all the data sent by the client.
int length;
while ((length = stream.Read(bytes, 0, bytes.Length)) != 0)
{
var copy = new byte[length];
Array.Copy(bytes, 0, copy, 0, length);
data.AddRange(copy);
}
}
receivedQueue.Add(data);
}
Also you should consider using AutoResetEvent or ManualResetEvent to be notified when new data is added to the collection so the thread that handle the data will know when data is received, and if you are using 4.0 you better switch off to using BlockingCollection instead of Queue.
What I do usually is using a thread pool with several threads.
Upon each new connection I'm running the connection handling (in your case - everything you do in the using clause) in one of the threads from the pool.
By that you achieve both performance since you're allowing several simultaneously accepted connection and you also limiting the number of resources (threads, etc') you allocate for handling incoming connections.
You have a nice example here
Good Luck
I'm struggling a bit with socket programming (something I'm not at all familiar with) and I can't find anything which helps from google or MSDN (awful). Apologies for the length of this.
Basically I have an existing service which recieves and responds to requests over UDP. I can't change this at all.
I also have a client within my webapp which dispatches and listens for responses to that service. The existing client I've been given is a singleton which creates a socket and an array of response slots, and then creates a background thread with an infinite looping method that makes "sock.Receive()" calls and pushes the data received into the slot array. All kinds of things about this seem wrong to me and the infinite thread breaks my unit testing so I'm trying to replace this service with one which makes it's it's send/receives asynchronously instead.
Point 1: Is this the right approach? I want a non-blocking, scalable, thread-safe service.
My first attempt is roughly like this, which sort of worked but the data I got back was always shorter than expected (i.e. the buffer did not have the number of bytes requested) and seemed to throw exceptions when processed.
private Socket MyPreConfiguredSocket;
public object Query()
{
//build a request
this.MyPreConfiguredSocket.SendTo(MYREQUEST, packet.Length, SocketFlags.Multicast, this._target);
IAsyncResult h = this._sock.BeginReceiveFrom(response, 0, BUFFER_SIZE, SocketFlags.None, ref this._target, new AsyncCallback(ARecieve), this._sock);
if (!h.AsyncWaitHandle.WaitOne(TIMEOUT)) { throw new Exception("Timed out"); }
//process response data (always shortened)
}
private void ARecieve (IAsyncResult result)
{
int bytesreceived = (result as Socket).EndReceiveFrom(result, ref this._target);
}
My second attempt was based on more google trawling and this recursive pattern I frequently saw, but this version always times out! It never gets to ARecieve.
public object Query()
{
//build a request
this.MyPreConfiguredSocket.SendTo(MYREQUEST, packet.Length, SocketFlags.Multicast, this._target);
State s = new State(this.MyPreConfiguredSocket);
this.MyPreConfiguredSocket.BeginReceiveFrom(s.Buffer, 0, BUFFER_SIZE, SocketFlags.None, ref this._target, new AsyncCallback(ARecieve), s);
if (!s.Flag.WaitOne(10000)) { throw new Exception("Timed out"); } //always thrown
//process response data
}
private void ARecieve (IAsyncResult result)
{
//never gets here!
State s = (result as State);
int bytesreceived = s.Sock.EndReceiveFrom(result, ref this._target);
if (bytesreceived > 0)
{
s.Received += bytesreceived;
this._sock.BeginReceiveFrom(s.Buffer, s.Received, BUFFER_SIZE, SocketFlags.None, ref this._target, new AsyncCallback(ARecieve), s);
}
else
{
s.Flag.Set();
}
}
private class State
{
public State(Socket sock)
{
this._sock = sock;
this._buffer = new byte[BUFFER_SIZE];
this._buffer.Initialize();
}
public Socket Sock;
public byte[] Buffer;
public ManualResetEvent Flag = new ManualResetEvent(false);
public int Received = 0;
}
Point 2: So clearly I'm getting something quite wrong.
Point 3: I'm not sure if I'm going about this right. How does the data coming from the remote service even get to the right listening thread? Do I need to create a socket per request?
Out of my comfort zone here. Need help.
Not the solution for you, just a suggestion - come up with the simplest code that works peeling off all the threading/events/etc. From there start adding needed, and only needed, complexity. My experience always was that in the process I'd find what I was doing wrong.
So is your program SUDO outline as follows?
Socket MySocket;
Socket ResponceSocket;
byte[] Request;
byte[] Responce;
public byte[] GetUDPResponce()
{
this.MySocket.Send(Request).To(ResponceSocket);
this.MySocket.Receive(Responce).From(ResponceSocket);
return Responce;
}
ill try help!
The second code post is the one we can work with and the way forward.
But you are right! the documentation is not the best.
Do you know for sure that you get a response to the message you send? Remove the asynchronous behavior from the socket and just try to send and receive synchronously (even though this may block your thread for now). Once you know this behavior is working, edit your question and post that code, and I'll help you with the threading model. Once networking portion, i.e., the send/receive, is working, the threading model is pretty straightforward.
One POSSIBLE issue is if your send operation goes to the server, and it responds before windows sets up the asynchronous listener. If you arent listening the data wont be accepted on your side (unlike TCP)
Try calling beginread before the send operation.