in server -(multi)client application [TCP]. I use Socket, NetworkStream, StreamReader and StreamWriter for each client i Accept in the server .. so i have couple of questions :
Do i have to dispose all of them when i want to close the connection with a client?
If the client Disposes the Socket that's connected with the server .. do i also have do dispose that socket in the server side ,or it closes automatically ?
in my code here :
Thread thAccept = new Thread(acceptClient);
Thread thJob;
private void acceptClient()
{
while (true)
{
Socket client = server.Accept();
Console.WriteLine(client.RemoteEndPoint+" has connected");
StreamReader reader = new StreamReader(new NetworkStream(client));
//is it ok to create an instance NetworkStream like this or i will have to dispose it later?
thJob = new Thread(Job);
thJob.Start(reader);
}
}
private void Job(object o)
{
StreamReader reader = (Socket)o;
try
{
string cmd = null;
while ((cmd = reader.ReadLine()) != null)
{
//(BLA BLA..)
}
}
catch
{
Console.WriteLine("Disconnected by catch");
}
finally
{
Console.WriteLine("Finally Done.");
reader.Dispose();
}
}
is that code fine to dispose all (needed to be disposed) objects?
This is not a duplicate.
Your code differs from the linked duplicate because in your code, the IDisposable is handed off to another thread.
The general rule is that if you create an object that implements IDisposable, then you're responsible for calling Dispose on it when you're finished with it. When possible, that should be done in a using block, to ensure that Dispose is always called. In your case, your code is not finished with the object until the other thread is exited. In that thread, you correctly call Dispose in the finally block.
If you had called Dispose on the NetworkStream, then it would have closed the StreamReader as well, which would defeat your purpose. I suspect it would be the same thing if you had called Dispose on the Socket. As such, your code is correct as-is.
The object on the client side has no relationship with the object on the server side, except through TCP/IP. The fact that the client may call Dispose on its socket doesn't mean that the server has to call Dispose on its socket. However, once the server is finished reading data from the socket, and the connection is closed, the server-side socket should be Disposed. I don't know for certain, but I believe that when the StreamReader is disposed, the underlying NetworkStream will be disposed, which should call Dispose on the socket from which the stream was created.
Your code is fine, except for some unrelated issues: you don't need to set cmd to null, since you're going to set the value in the next statement. Also, you should not use an empty catch block like that. You have no idea what exception was thrown, but you will ignore it anyway, without even logging or displaying the exception. At the least, you should do
catch (Exception ex)
{
Console.WriteLine("Disconnected by exception " + ex.ToString());
}
finally
{
Console.WriteLine("Finally Done.");
reader.Dispose();
}
Related
I have written Windows service, which perform Modbus WriteMultipleRegisters function call over TCP using NModbus library to 3-party devices every 10 minutes (ticks of System.Threading.Timer).
Occasionally this connection hang up open usually during network problems. As the device accepts only one Modbus connection at time and others are refused, connection during all next ticks fail with SocketException - ConnectionRefused.
But the device automatically closes connections which don't respond after short time. Something must keep connection open at my side even for two days. What's more when my Service is restarted, everything is fine again. So there is definitely some forgotten open connection. But I didn't manage to reproduce this bug in dev, so I don't where/when.. connection hang up. I only know that next connection is refused.
I do the modbus function call with this part of code:
using (TcpClient client = new TcpClient(device.ip, 502))
{
using (Modbus.Device.ModbusIpMaster master = Modbus.Device.ModbusIpMaster.CreateIp(client))
{
master.WriteMultipleRegisters(500, new ushort[] { 0xFF80 });
}
}
device.ip is string containing IP address of device - it's correct, confirmed from SocketException details.
As I'm using using statement dispose is called on both objects.
I have looked trough NModbus source code and everything is disposed correctly.
Any idea how its possible that with this code connection is not closed?
I agree with nemec. If you review the documentation for TcpClient.Dispose if does not specifically mention closing the connection. It frees managed and unmanaged resources by default, but it may not correctly tear down the connection.
Try changing your code to:
using (TcpClient client = new TcpClient(device.ip, 502))
{
try
{
using (Modbus.Device.ModbusIpMaster master = Modbus.Device.ModbusIpMaster.CreateIp(client))
{
master.WriteMultipleRegisters(500, new ushort[] { 0xFF80 });
}
}
catch(Exception e)
{
// Log exception
}
finally
{
client.Close();
}
}
That way you are doing a clean close before dispose and it should clean up even if the Modbus protocol throws some kind of exception.
did you play with TcpClient.LingerState Property
defualt setting could cause problems with resetting winsock
check it out
http://msdn.microsoft.com/pl-pl/library/system.net.sockets.tcpclient.lingerstate%28v=vs.110%29.aspx
This is not an answer, but a comment with code. We have this same issue on some of our installed computers, but not all of them. The issue itself is also very intermittent, sometimes going months without happening. I am hoping someone can find an answer. Here is our brute force destroy / reconnect code that does not work:
try
{
try
{
try
{
// Close the stream
var stream = _tcpClient.GetStream();
if (stream != null)
stream.Close();
}
catch { }
try
{
// Close the socket
if (_tcpClient.Client != null)
_tcpClient.Client.Close();
}
catch { }
// Close the client
_tcpClient.Close();
_tcpClient = null;
}
catch { }
if (_device != null)
{
_device.Dispose();
_device = null;
}
}
catch { }
System.Threading.Thread.Sleep(1000);
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 was told several times that async is better or that I should use async instead of sync sockets and as such started learning it, but am already having difficult.
I've got the basic feel of how the callback works and how to establish a connection.
I am using this msdn code as reference!
A few problems I am having with the code:
Currently that code will connect to the server, send a text, read the response and exit. How do I do so I can keep receiving the data until either the server disconnects me and/or I end it by myself ? I am not much sure on how I should do it, if I would need to wrap it on a thread with while or simple call that Receive again once the ReceiveCallback is done.
Another things I've noticed is when it connects, the socket is assigned to client but the code itself is always reassigning the client socket which I don't understand very well compared to the sync socket we have a main socket that we are always consulting etc.
I am not sure on how old the reference I am using is but would appreciate if you could help me with examples of what I have pointed out as it is easier for me to understand.
UPDATE:
private void SetupRecieveCallback(Socket sock)
{
new Thread(
delegate()
{
while (isReceiving)
{
_receiveQueue.Reset();
try
{
AsyncCallback recieveData = new AsyncCallback(OnRecievedData);
sock.BeginReceive(m_byBuff, 0, m_byBuff.Length, SocketFlags.None, recieveData, sock);
}
catch (Exception ex)
{
_logger.Error("Setup Recieve Callback failed! " + ex.Message);
}
_receiveQueue.WaitOne();
}
}
).Start();
/*
// The original code
try
{
AsyncCallback recieveData = new AsyncCallback(OnRecievedData);
sock.BeginReceive(m_byBuff, 0, m_byBuff.Length, SocketFlags.None, recieveData, sock);
}
catch (Exception ex)
{
_logger.Error("Setup Recieve Callback failed! " + ex.Message);
}
*/
}
Simply call BeginReceive() again in the callback to keep receiving. When the server breaks the connection then your callback will be called and EndReceive() throws an ObjectDisposedException. That's how you know to stop calling BeginReceive().
Second question is harder to decode (ask only one). I'm guessing you are puzzled about this statement:
private static void ConnectCallback(IAsyncResult ar) {
try {
// Retrieve the socket from the state object.
Socket client = (Socket) ar.AsyncState;
// etc..
No reassigning the socket is happening here. The code simply retrieves a reference to the original socket. Which is a useful technique, it allows this callback to be used by more than one connection. The ar.AsyncState value got to be the socket by this statement:
client.BeginConnect( remoteEP,
new AsyncCallback(ConnectCallback), client);
Note how client is passed to the AsyncCallback constructor. The exact same client that's retrieved in the callback. Any object can be passed.
I have a simple class that handles the connection being made between a client and server.
To let more than one user communicate with the server at one time each new Client connection is made on a separate thread.
In this class I create two streams that act as the inbound and outbound streams for the client. I create the fields first and then initialise the object in a separate method, simply because the object is used in several other places.
I've come to the point where I want to refactor the code to make it more robust, my first port of call was memory management. I've come to love the using() statement but noticed that I can't really see a way to do implement it due to the way the code is structured.
This means I have a fairly annoying method that is just used for closing the underlying connections and nothing more.
Furthermore, I came to implement exception handling and was curious whether the notion of wrapping the entire code in a method with a try{} statement and then having sequential catch() blocks with the applicable exception types was the best idea.
I hope I explained myself correctly, I'll post a snippet for you to look at.
Thanks!
//Fields
TcpClient tcpClient;
//The thread that will send information to the client
private Thread thrSender;
private StreamReader srReceiver;
private StreamWriter swSender;
private string currentUser;
private string strResponse;
//The constructor of the class takes in a TCP connection
public Connection(TcpClient tcpCon)
{
tcpClient = tcpCon;
//The thread that accepts the client and waits messages
thrSender = new Thread(AcceptClient);
//The thread calls the AcceptClient method
thrSender.Start();
}
private void CloseConnection()
{
//Close the currently open objects
tcpClient.Close();
srReceiver.Close();
swSender.Close();
}
//Occurs when a new client is accepted
private void AcceptClient()
{
srReceiver = new StreamReader(tcpClient.GetStream());
swSender = new StreamWriter(tcpClient.GetStream());
//Read account information from the client
currentUser = srReceiver.ReadLine();
//Examine response from client
if (currentUser != "")
{
//Store the user name in the hash table
if (ChatServer.htUsers.Contains(currentUser) == true)
{
//0 means not connected - Writes error to Client and Server log
swSender.WriteLine("0|This username already exists.");
swSender.Flush();
CloseConnection();
return;
}
//More if/else if/else statements
//...
}
}
You can dispose of the two streams fairly easily within the AcceptClient method by making them local variables since they aren't referenced elsewhere something like this:
private void AcceptClient()
{
using (StreamReader srReceiver = new StreamReader(tcpClient.GetStream()))
{
using (StreamWriter swSender = new StreamWriter(tcpClient.GetStream()))
{
// ...
}
}
}
The tcpClient is more tricky because it is being created on one thread and cleaned up on another. Unless you can change that then perhaps the best option is going to be to implement the cleanup within a try/finally.
private void AcceptClient()
{
try
{
using (StreamReader srReceiver = new StreamReader(tcpClient.GetStream()))
{
using (StreamWriter swSender = new StreamWriter(tcpClient.GetStream()))
{
// ...
}
}
}
finally
{
tcpClient.Dispose();
}
}
The finally clause will get called whether or not the try clause throws an exception.
In the code below I have a StreamReader reading from a network stream. This code normally will run fine for days. I ran into a problem where all of a sudden StreamReader.ReadLine() started returning null.
According to Microsoft documentation StreamReader.ReadLine() will return null when it has reached the end of the input stream. This doesn't make sense to me when the underlying stream is a NetworkStream. Shouldn't ReadLine() just block until the network stream receives data?
This is the first time I ran into this problem and I have not been able to duplicate it. What could cause this?
Context: the application receives CDR records from a phone switch. The phone switch connects to the application and sends plain old text records. After the switch connects it will remain connected and keep sending records for eternity unless something breaks.
private void ProcessClient(TcpClient client)
{
try
{
using (NetworkStream stream = client.GetStream())
{
using (StreamReader reader = new StreamReader(stream))
{
//continue processing while service is on
while (m_RunService & client.Connected)
{
string curLine = reader.ReadLine();
//code here does stuff to string
//will catch any exceptions that have to do with
//processing the string
}
}
}
}
catch (Exception ex)
{
//write to log
}
}
Here is the code that starts the listener:
private void Listen()
{
try
{
while (m_RunService)
{
try
{
m_TcpClient = m_TcpListener.AcceptTcpClient();
//run on same thread, should only ever be 1 cnx at a time
ProcessClient(m_TcpClient);
}
catch (Exception ex)
{
//write to log
}
finally
{
m_TcpClient.Close();
}
}
}
finally
{
m_TcpListener.Stop();
}
}
The StreamReader will block until it receives data or the connection is closed. It sounds like an exception occurred at the server side, it closed the connection, and the client side received no data.
If the NetworkStream does not have data available, the call to ReadLine() will return null because it assumes it has reached the end of the stream.
Try checking NetworkStream.CanRead and NetworkStream.DataAvailable before calling ReadLine. If the connection has not closed, manually block for a time then try your read again.
EDIT
You can check to see if the connection is still open by making a Send or using the underlying Socket:
The Connected property gets the
connection state of the Socket as of
the last I/O operation. When it
returns false, the Socket was either
never connected, or is no longer
connected.
The value of the Connected property
reflects the state of the connection
as of the most recent operation. If
you need to determine the current
state of the connection, make a
nonblocking, zero-byte Send call. If
the call returns successfully or
throws a WAEWOULDBLOCK error code
(10035), then the socket is still
connected; otherwise, the socket is no
longer connected.
That pretty much sounds like the stream has closed. Otherwise yes: it would block. My guess: network #fail