Given the simple socket client class below, connect it to a TCP server (I use SocketTest3, freely available online). Then disconnect the server and wait for a bit. You should get a LockRecursionException.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace SocketRwlTest
{
public class SocketRwlTest
{
private Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
private readonly ReaderWriterLockSlim rwl = new ReaderWriterLockSlim();
private const int maxLength = 200;
public SocketRwlTest(IPAddress address, ushort port)
{
client.Connect(new IPEndPoint(address, port));
ReceiveOne();
}
private void ReceiveOne()
{
rwl.EnterReadLock();
try
{
var inArray = new byte[maxLength];
client.BeginReceive(inArray, 0, maxLength, 0,
new AsyncCallback(ReceivedCallback),
inArray);
}
finally
{
rwl.ExitReadLock();
}
}
private void ReceivedCallback(IAsyncResult ar)
{
client.EndReceive(ar);
ReceiveOne();
}
}
}
I don't understand why it happens in the simplified example given. I know I should stop calling ReceiveOne as soon as I receive a zero-length message, but this is more of an exercise. I wondered if a similar bug could maintain a constant stream of callbacks running in the background and stealing resources without obviously bad things happening. I must admit I wasn't expecting this particular exception.
Question 1: Why does this happen? Are BeginXYZ methods perhaps allowed to execute callbacks instantly, on the same thread? If that's the case, who's to say this couldn't happen during normal runtime?
Question 2: Are there ways to avoid getting this exception while still maintaining the "desired" behaviour in this case? I mean fire a non-stopping stream of callbacks.
I'm using Visual Studio 2010 with .NET 4.
Question 1: Why does this happen? Are BeginXYZ methods perhaps allowed to execute callbacks instantly, on the same thread? If that's the case, who's to say this couldn't happen during normal runtime?
As described by mike z in the comments, the BeginReceive() method is not required to execute asynchronously. If data is available it will execute synchronously, calling the callback delegate in the same thread. This is by definition a recursive call, and so would not be compatible with the use of a non-recursive lock object (such as the ReaderWriterLockSlim you're using here).
This certainly can happen "during normal runtime". I'm not sure I understand the second part of your question. Who's to say it can't happen? No one. It can happen.
Question 2: Are there ways to avoid getting this exception while still maintaining the "desired" behaviour in this case? I mean fire a non-stopping stream of callbacks.
I'm afraid I also don't know what you mean by "fire a non-stopping stream of callbacks".
One obvious workaround is to enable recursion on the ReaderWriterLockSlim object by passing LockRecursionPolicy.SupportsRecursion to its constructor. Alternatively, you could check the IsReadLockHeld property before trying to take the lock.
It is not clear from your code example why you have the lock at all, never mind why it's used in that specific way. It's possible the right solution is to not hold the lock at all while you call BeginReceive(). Use it only while processing the result from EndReceive().
Related
According to this MSDN article, the socket.EndConnect method should be called in the AsyncCallback delegate provided in the original socket.BeginConnect call.
What is not clear (and the MSDN article is silent here) is whether EndConnect should be called after a timeout (and the socket is NOT connected). socket.EndConnect throws an exception in this case.
What is the proper procedure to follow after timeout? What are the consequences if EndConnect is not called (either after a successful connection or timeout without connection)? My code appears to work fine without calling EndConnect.
Here is some example code covering the main ideas in the question:
// Member variables
private static ManualResetEvent m_event;
private static Socket m_socket;
// Constructor of class
public static CMyTestConnection()
{
// Create an event that can be used to wake this thread when the connection completes
m_event = new ManualResetEvent(false);
}
private static void TestConnection(object sender, EventArgs e)
{
// Create connection endpoint
IPAddress ip = IPAddress.Parse("200.1.2.3"); // Deliberately incorrect
IPEndPoint ipep = new IPEndPoint(ip, 12345); // Also deliberately incorrect
EndPoint ep = (EndPoint)ipep;
// Attempt connection
m_event.Reset();
m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
m_socket.BeginConnect(ep, ConnectCompletedCallback, m_socket);
}
private static void ConnectCompletedCallback(IAsyncResult ar)
{
// The asynchronous connection call has completed. Either we have connected (success) or
// timed out without being able to connect (failure).
m_event.Set();
Socket s = (Socket)ar.AsyncState;
if (s.Connected)
{
// Success...should EndConnect only be called here?
s.EndConnect(ar);
}
else
{
// Or should EndConnect also be called here (in a try/catch block)?
s.Close();
}
}
You invited me to this chat room. I am assuming this is the question to which you're referring, but it's hard for me to know for sure. Your message in the chat room doesn't have a real URL. I looked at your question links in your profile, and the only one I recognize is this one, which isn't closed at the moment. So there's no need to vote to re-open.
That said, the answer is still the same as already provided in the comments: you always call the EndXXX method when you've called BeginXXX (the few known exceptions don't apply here). There's nothing in your question, even after the recent edit, that would indicate what more you need.
You don't show how the timeout is implemented, so there's not even enough information to understand the code you posted. But if you are closing the socket, thus causing your callback to be invoked where EndConnect() will throw an exception, you should be calling EndConnect(). Failing to do so can potentially leave unmanaged resources dangling, which would then eventually be exhausted, or at the very least lead to performance problems.
The source code for .NET is readily available, so you can easily examine the implementation yourself. In the case of Socket.EndConnect(), we can see that for the current implementation, if the socket has already been disposed, all that happens is an exception is thrown. So, in theory, you could ignore sockets that have already been closed. I.e. this is an exception to the general concern about leaving resources dangling, in the specific "socket is already closed" scenario. But only if your timeout is implemented by closing the socket.
There are a couple of problems here though, related to race conditions:
Depending on how the timeout is implemented (you didn't share that part, so the question is still incomplete), you may have code that got as far as starting to call Socket.Close(), but which has not set the disposed flag. You'll be dealing with a connected socket that is about to become disconnected, and you need to have try/catch in place to handle that scenario.
Your callback assumes (it seems…again, there's not enough context in your question) that the Connected property is a reliable way to detect that there's been a timeout, but the Connected property could theoretically be reset to false after being connected, but before your callback gets to execute (e.g. some other type of error on the socket).
As far as the question of calling EndConnect() on a successful connection, that is much more clear: you must do so. If your code appears to work even though you haven't, that's just you getting lucky. We can see in the implementation that the EndConnect() method does useful work to configure the socket state when called after a successful connection, so if you fail to call the method, your socket will be in some indeterminate, incompletely configured state.
Naturally, if your timeout is implemented in some other way, where the socket is not closed before the callback is invoked, then you are in the same situation as if the connection had completed, and you must call EndConnect() to ensure that the appropriate cleanup and socket configuration occurs. I.e. that would be the same as the "successful connection" scenario.
The bottom line is, there is zero benefit to not calling EndConnect() in the event of a close/dispose-based timeout. The only hypothetical benefit might be that you can avoid try/catch, but you can't get away without that, because of the race conditions that exist. And if there's not such a timeout, not only is there not a benefit to not calling the method, there is real harm in failing to call it.
On a related note, there's not enough context in your question to make any real assessments of the rest of your code (since you didn't show how you're implementing the timeout, nor how the rest of your network I/O is handled). But I will say that in most cases, the "reuse address" option is unnecessary and should not be used. Most people wind up using it because they get into a situation where they can't start a new listening socket after they have somehow stopped a previous one, but that problem only comes up with the first listening socket and/or associated connected sockets have not been closed or shutdown correctly. The correct approach in that case is to handle the socket closure/shutdown correctly, not to add to the problem by setting "reuse address".
I was trying to develop a multicast receiver program and socket initialization was done as shown below:
public void initializeThread()
{
statuscheckthread = new Thread(SetSocketOptions);
statuscheckthread.IsBackground = true;
}
private void Form1_Load(object sender, EventArgs e)
{
rxsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
iep = new IPEndPoint(IPAddress.Any, 9191);
rxsock.Bind(iep);
ep = (EndPoint)iep;
initializeThread();
statuscheckthread.Start();
}
public void SetSocketOptions()
{
initializeThread(); //re-initializes thread thus making it not alive
while (true)
{
if (NetworkInterface.GetIsNetworkAvailable())
{
bool sockOptnSet = false;
while (!sockOptnSet)
{
try
{
rxsock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("224.50.50.50")));
rxsock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 64);
sockOptnSet = true;
}
catch
{
//Catch exception here
}
}
}
break; // Break out from loop once socket options are set
}
}
When my PC is not connected to a network, SetSocketOption method was throwing exception and even after network is connected,
I was unable to receive data because socket options are not set.
To avoid this I used a thread which runs in the background checking
for network availability and once network is available, it sets the socket options.
It works properly in some PC's but in some others, NetworkInterface.GetIsNetworkAvailable()
returned true before network got connected
(while network was being identified) .
So, to make sure Socket options are set, I used a bool variable sockOptnSet
which is set as
true if all the statements in the try block is executed as shown inside the method public void SetSocketOptions()
This program works fine in all PC's I tried, but I am doubtful about how much I can rely on this to work.
My questions are:
1) Is this good practice?
2) If not, what are the possible errors or problems it may cause? And how can I implement it in a better way?
Is this a good practice?
No, not a good practice. The vast majority of exceptions, including your first one, fall in the category of vexing exceptions. Software is supposed to work, worked well when you tested it, but doesn't on the user's machine. Something went wrong but you do not know what and there isn't anything meaningful that you can do about it. Trying to keep your program going is not useful, it cannot do the job it is supposed to do. In your case, there's no hope that the socket is ever going to receive data when there is no network. And, as you found out, trying to work around the problem just begets more problems. That's normal.
If this is bad practice, how can I implement it in a better way?
You need help from a human. The user is going to have to setup the machine to provide a working network connection. This requires a user interface, you must have a way to tell a human what he needs to do to solve your problem. You can make that as intricate or as simple as you desire. Just an error message, a verbatim copy of the Exception.Message can be enough. Writing an event handler for the AppDomain.CurrentDomain.UnhandledException event is a very good (and required) strategy. Microsoft spent an enormous amount of effort to make exception messages as clear and helpful as possible, even localizing them for you in the user's native language, you want to take advantage of that. Even if the exception message is mystifying, a quick Google query on the message text returns hundreds of hits. With this event handler in place, you don't have to do anything special. Your program automatically terminates and your user knows what to do about it.
You can certainly make it more intricate, you discovered that SetSocketOption() is liable to fail right after the network becomes available but works when you wait long enough. So this is actually an error condition that you can work around, just by waiting long enough. Whether you should write the code to handle this is something that you have to decide for yourself. It is something you write when you have enough experience with the way your program behaves, you never write it up front. Usually as a result from feedback from the users of your program.
Some good advice in the comments, lets' expand on it.
Firstly, I would put all this socket code in to its' own class, outside of the form. This makes it its' own entity and semantically easier to understand. This class could have a property Initialised, which is initially set to false. The first thing you do in your form is call an Initialise method on this class which attempts to set socket options and catches the relevant exceptions if the network is not available. If it is available, we set our Initialised property to true.
If not available, we set a single timeout (see System.Threading.Timer) that calls this same function (potentially with a retry count) after 'x' seconds. Once again we'll find ourselves back in this Initialise function, perhaps with a retry count mentioned at the beginning. Once again, if it is available, we're good - if not, set the timer again. Eventually, after 'x' retries if we're not initialised we can throw an exception or set some other failure property to indicate that we can't proceed.
Your Form class can periodically check (or hook in to an event) to determine whether the socket is now ready for communication. In case of failure you can gracefully quit out, or because our class is nice and abstracted, attempt to start the whole process again.
i have a multi-threaded application which wants to send a sequence of data to an external device via a serial port. the sequence of data is a typical cmd - response protocol (ie: a given thread sends a sequence of bytes then waits to read a response which is typically an ack and then it might send another sequence).
what we are are looking to do is declare a sequence of code has exclusive access to this resource until it is done and if another thread wants access to the same external resouce, it waits.
this seems like what LOCK does, but all the examples that i have seen show lock being used to protect a specific block of code, not to serialize access to a resource.
so programatically can i have
Object serialPortLock = new Object();
and in different parts of my program use a construct that looks like:
Lock (serialPortLock)
{
// my turn to do something that is not the same as what
// someone else wants to do but it acts on the same resource
}
the c# documentation talks about using Mutex as a more robust version of Lock. is that whats required here?
Yes, your pattern is correct as long as your program is the only software accessing the serial port.
You have not posted your entire code. If the class that contains serialPortLock has multiple instances, then you MUST make serialPortLock a static. This is normally best practice.
class MySerialPort
{
static object synchLock = new object();
public void DoSomething()
{
lock (synchLock)
{
// whatever
}
}
}
Locking should work fine in the case you've suggested as long as you are locking around all access to any of the object instances that point at the external resource.
I'm using Sockets in my Silverlight application to stream data from a server to a client.
However, I'm not quite sure how timeouts are handled in a Silverlight Socket.
In the documentation, I cannot see anything like ReceiveTimeout for Silverlight.
Are user-defined timeouts possible? How can I set them? How can I get notifications when a send / receive operation times out?
Are there default timeouts? How big are they?
If there are no timeouts: what's the easiest method to implement these timeouts manually?
I've checked the Socket class in Reflector and there's not a single relevant setsockopt call that deals with timeouts - except in the Dispose method. Looks like Silverlight simply relies on the default timeout of the WinSock API.
The Socket class also contains a "SetSocketOption" method which is private that you might be able to call via reflection - though it is very likely that you will run into a security exception.
Since I couldn't find any nice solution, I solved the problem manually by creating a System.Threading.Timer with code similar to the following:
System.Threading.Timer t;
bool timeout;
[...]
// Initialization
t = new Timer((s) => {
lock (this) {
timeout = true;
Disconnected();
}
});
[...]
// Before each asynchronous socket operation
t.Change(10000, System.Threading.Timeout.Infinite);
[...]
// In the callback of the asynchronous socket operations
lock (this) {
t.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
if (!timeout) {
// Perform work
}
}
This handles also cases where a timeout occurs which is produced by simple lag, and lets the callback return immediately if the operation took too much time.
I solved this issue for my project sharpLightFtp like:
Created a class which is injected in the UserToken-property of an instance of System.Net.Sockets.SocketAsyncEventArgs and has an System.Threading.AutoResetEvent, which is used to receive a signal after ConnectAsync, ReceiveAsync and SendAsync with a timeout (like here: line 22 for getting a custom enhanced SocketAsyncEventArgs-instance, line 270 for creating and enhancing the SocketEventArgs-instance, line 286 for sending the signal and line 30 for waiting)
I've been doing a lot of research on how best to write "correct" network code in C#.
I've seen a number of examples using the "using" statement of C#, and I think this is a good approach, however i've seen inconsistent use of it with various expressions.
For instance, suppose I have some code like this:
TcpClient tcpClient = new TcpClient("url.com", 80);
NetworkStream tcpStream = tcpClient.GetStream();
StreamReader tcpReader = new StreamReader(tcpStream);
StreamWriter tcpWriter = new StreamWriter(tcpStream);
Obviously, this code is going to be very flaky. So, i've seen some code that puts the using on the tcpClient, which seems good. However, doesn't NetworkStream also have resources that need cleaning up? What about StreamReader/Writer?
Do I need to wrap all 4 statements in nested using statements?
And if so, what happens when the time has come to dispose? Won't StreamWriter close the stream and consequently the socket? Then what happens when StreamReader, then NetworkStream, then TcpClient each go through their disposals?
Which brings up another question. WIth both StreamReader and StreamWriter composed of the same stream, who owns it? Don't they both think they own it, and will thus both try to destroy it? Or does the framework know that the stream has already been destroyed and just silently ignore it?
It almost seems like the using statement is only necessary for the last statement in the chain, but then what happens if an exception is thrown in GetStream()? I don't think it would properly clean up the socket then, so it seems redundant usings are necessary to ensure this doesn't happen.
Does anyone know of any good, recent books on network programming with .net, and prefeably c# that include chapters on exception handling and resource management? Or maybe any good articles online? All the books I can find are from the .NET 1.1 era (Network Programming for the Microsoft .NET Framework, Network Programming in.NET, etc..), so this seems like a topic that needs some good resources.
EDIT:
Please, don't let Marc's very good comment stop anyone else from commenting on this :)
I'd like to hear anyone elses book recommendations or opinions on resource management, especially in regard to asynchronous usage.
Generally, objects should internally handle multiple Dispose() calls, and only do the main code once; so a stream getting Dispose()d multiple times is not usually a problem. Personally, I would use lots of using there; note that you don't need to indent/nest, though (unless different levels have different life-times):
using(TcpClient tcpClient = new TcpClient("url.com", 80))
using(NetworkStream tcpStream = tcpClient.GetStream())
using(StreamReader tcpReader = new StreamReader(tcpStream))
using(StreamWriter tcpWriter = new StreamWriter(tcpStream))
{
...
}
As you say, this ensures that if an error happens during initialization, everything is still cleaned up correctly. This also ensures that every level gets a chance (in the right order) to deal correctly with any buffered data, etc.
Re ownership; NetworkStream is actually an oddity in the first place... most streams are either input xor output. NetworkStream bends a few rules and shims two directions into one API; so this is an exception... normally the ownership would be clearer. Additionally, many wrappers have a flag to determine whether they should close the wrapped stream. StreamReader doesn't, but some do (such as GZipStream, which has a leaveOpen ctor option). If you don't want to flow ownership, this is an option - or use a non-closing stream intermediary - one is here (NonClosingStream or similar).
Re books; I picked up a copy of "TCP/IP Sockets in C#: Practical Guide for Programmers" (here) - adequate, but not great.
If an object supports IDisposable, it's best to put it in a using {} block because the dispose method gets called automatically for you. This also makes for less code on your part. It is important to note the using a 'using' doesn't handle any exceptions. YOu still have to do that if you want to handle any errors. Once the using block goes out of scope, so does your object.
Old Style Code
object obj;
try
{
obj= new object();
//Do something with the object
}
catch
{
//Handle Exception
}
finally
{
if (obj != null)
{
obj.Dispose();
}
}
Newer Style Code
try
{
using (object obj = new object())
{
//Do something with the object
}
catch
{
//Handle Exception
}
What about sockets?
Is it OK to do:
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Connect(serverEndPoint, m_NegotiationPort);
.
.
.
serverSocket.Close();
or better
using (Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
{
.
.
.
}