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.
Related
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.
i want to get signal from port and I used these functions for receiving data,but I sometimes get this exception on line thread.join() :
System.IO.IOException was unhandled
Message="The I/O operation has been aborted because of either a thread exit or an application request.
when I insert a breakpoint and debug it, it goes correct until on line thread.join() and the UI then is stopped and nothings occurs.
also when I run my program in release mode it works correctly but the problem is with debug mode,what is goes wrong and how I can solve this problem?
thnx.
public SignalReader()
{
thread = new Thread(new ThreadStart(ThreadMain));
}
public void Start(string portName, int rate)
{
Stop();
try
{
port = new SerialPort(portName, rate);
port.Open();
}
catch
{
;
}
thread.Start();
}
public void Stop()
{
try
{
if (port != null)
{
if (port.IsOpen) port.Close();
if (thread.IsAlive) thread.Join();
port.Dispose();
port = null;
}
}
catch (Exception ex)
{
MessageBox.Show("4:" + ex.ToString());
}
}
when i swap the order of closing the port and joining the thread:
...
thread.Join();
port.Close();
...
the same story exists.
You are jerking the floor mat, closing the port while it is being used. Most typically in a SerialPort.Read() call. So, yes, that call is going to fail, there's no floor mat anymore. What's missing is a catch block that catches that exception and lets the thread end gracefully. And complete the Join() call.
It is not entirely unusual to do this, as long as you can make sure that the thread is actually blocking on such a Read call. That's not usually very hard to guarantee. But certainly fret about not getting that exception in the Release build, that's not normal. Use the debugger's Debug + Window + Threads to see what's going on in that worker thread.
So just add the required try/catch to fix your problem. Using the SerialPort.DataReceived event is an entirely different approach. Not cleaning up at all, just setting the thread's IsBackground property to true so it automatically dies when the program terminates is also a quite acceptable solution.
The error you are receiving is because of that Stop() you are using in:
public void Start(string portName, int rate)
{
Stop();
try
{
port = new SerialPort(portName, rate);
port.Open();
}
catch
{
;
}
thread.Start();
}
The app is doing something already and when you call this it closes a port is being in use somewhere.
Try removing it and you will get an exception in the Start method if the port is not closed. It will give you a better idea where this error comes from. Also could you paste the part of the code where you are using these methods?
My asynchronous connect code is very rudimentary and is as followed:
private Socket _socket;
public void Connect(IPEndPoint remoteEndPoint, bool persistentConnection)
{
_logger.Trace("Attempting To Connect To " + remoteEndPoint.Address);
_remoteEndPoint = remoteEndPoint;
_persistentConnection = persistentConnection;
_socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
_socket.BeginConnect(_remoteEndPoint, ConnectCallback, null);
}
The Connect() method is accompanied by ConnectCallback() which is the where the problem I will describe shortly occurs:
private void ConnectCallback(IAsyncResult asyncResult)
{
try
{
_socket.EndConnect(asyncResult);
_logger.Trace("Successfully Connected To " + _remoteEndPoint.Address);
}
catch (SocketException)
{
_logger.Trace("Failed To Connect To " + _remoteEndPoint.Address);
if (_persistentConnection)
{
Thread.Sleep(TimeSpan.FromSeconds(3));
Connect(_remoteEndPoint, true);
return;
}
}
_socketWriter.AssignSocket(_socket);
_socket.BeginReceive(..);
}
My networking code is encapsulated within a single assembly. Today I decided to reference the assembly from another applications and found the ConnectCallback method to behave very oddly.
I make a call to Connect() when the server application is not running. This means it is not physically possible for the connection to succeed. Because the remote end point is not available, I would expect EndConnect to throw an exception. Instead EndConnect appears to succeed because even though the socket is not really connected, my code proceeds to make a call to _socket.BeginReceive which of course, throws an exception because the socket is not connected.
What is especially bizarre is that if I place a break point on the opening try brace and step-through the call back code the exception is thrown and handled.
This happens on local host.
Why am I experiencing this behaviour and how can I ensure that EndConnect throws a SocketException is the connection cannot established consistently?
You only return from the catch if _persistentConnection is true. If not, you call BeginReceive() anyway.
I use VS2012 for my project, I am handling the Socket exception when server cannot send message to target machine but It occurs that when It cannot send msg (I already put it in trycatch) Debugger just break in catch block and say the error without send forward to parent catch block. Please tell me, if I did something wrong.
private void sendMessageToTarget(string Message, IPAddress targetAddress, int port)
{
TcpClient client = new TcpClient();
IPEndPoint server = new IPEndPoint(targetAddress, OUT_MESSAGE_PORT);
Thread senderThread = new Thread(new ThreadStart(delegate()
{
try
{
client.Connect(server);
MemoryStream memstream = new MemoryStream();
NetworkStream netstream = client.GetStream();
byte[] sentString = Encoding.ASCII.GetBytes(Message);
netstream.Write(sentString, 0, sentString.Length);
memstream.Close();
netstream.Close();
client.Close();
}
catch (SocketException ex)
{
throw;
}
}));
senderThread.Start();
} // Sending Message Method
Above is my code for sending message to target
try
{
sendMessageToTarget("CONN_CHECKER", target, OUT_MESSAGE_PORT);
}
catch (Exception se)
{
ConnectedUsers.Remove(target.ToString());
UpdateConnectedUserToTeacher();
if (NeedFollowStudents.Contains(target.ToString()))
{
NeedFollowStudents.Remove(target.ToString());
}
UserLostConnection(this, new EventArgs());
}
And this is the method in another function that I want the action to be performed.
There is no magical marshalling exceptions from one thread to another. It is even almost guaranteed that code after senderThread.Start(); will be executed before code in the thread's delegate.
You function that you pass to Thread constructor becomes top level function on a new thread. If such function throws exception (like you do) this exception will go to AppDomain.UnhandledException event and than normally terminates application.
Your options
revert to synchronous code (all code on one thread)
use existing asynchrnous methods that will notify your code about end of operation. Depending on approach notification can be either via event (similar to WebClient.DownloadStringAsync ) or via callback and calling EndXXXXX like Socket.BeginSend
use async
manually implement synchronization and marshalling exception to original thread.
Note that only synchronous version of the code will work the way you want, all other that use multiple threads will not be able to return exception to the same "parent function" (using async will at least allow your code look the way you want even if it will not work the same way).
This is just a guess, but I believe you should only put a Try/Catch in the parent function and not in the child. When the exception occurs it will show in the parent method. The way you have it written will catch the exception in the child method and it will not get passed back to your parent method.
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.