Socket.Disconnect vs Socket.Close - c#

What is the difference and which rules I must follow when working with socks?
I'm writing simple daemon, which must listen port and do some actions.

Socket.Close calls Dispose (but it's undocumented).
When using a connection-oriented Socket, always call the Shutdown method before closing the Socket. This ensures that all data is sent and received on the connected socket before it is closed. (msdn)
Your code should looks like this (at least I'd do it like this):
using (var socket = new Socket())
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
The Disconnect method takes a single parameter bool reuseSocket , according to msdn:
reuseSocket
Type: System.Boolean
true if this socket can be reused after the current connection is closed; otherwise, false.
which basically means, when you set reuseSocket to false it will be disposed after you close it.
The Shutdown method will not disconnect your socket, it will just disable sending/receiving data.

Related

C# Sockets: accept a socket, ignore its message, send one back

We have a C# server that receives TCP messages using sockets. The normal flow is to call socket.Accept(), use socket.BeginReceive() and socket.EndReceive() to receive the message, then use socket.Send() to send a response. This works fine.
When too many requests come in at once, however, we want to reject the overflow immediately, so we don't overwhelm the server. It's easy enough to close the socket directly after Accept(); but that doesn't allow us to send a meaningful "too busy" message back to the client.
What I'd like to do is simply call Accept(), then call Send(), without receiving the incoming message. I have tried this, and the server claims to send my data, but my client receives nothing but an empty response. I have tried using both the synchronous Send() and the asynchronous BeginSend()/EndSend(), but neither gets the message back to the client.
Is it possible to send a message on an accepted socket without first receiving the incoming message? If so, is there a piece I'm missing to make it work?
Here's a code snippet showing what I'm trying to do:
while (!_Done)
{
Socket socket = null;
try
{
socket = _ListeningSocket.Accept();
}
catch (Exception) { }
if (socket != null)
{
if (TooBusy())
{
// My new code
byte[] send = GetTooBusyResponse();
int ret = socket.Send(send);
Console.WriteLine("socket.Send() returned " + ret);
socket.Close();
socket = null;
}
else
{
// Existing, working code (using custom objects)
ClientConnection connection = new ClientConnection(this, socket, !_RequireAuthentication);
lock (_ConnectionsToken)
_Connections.Add(connection);
connection.BeginReceive();
}
}
}
According to MSDN,
The Close method closes the remote host connection and releases all
managed and unmanaged resources associated with the Socket. Upon
closing, the Connected property is set to false.
For connection-oriented protocols, it is recommended that you call
Shutdown before calling the Close method. This ensures that all data
is sent and received on the connected socket before it is closed.
If you need to call Close without first calling Shutdown, you can
ensure that data queued for outgoing transmission will be sent by
setting the DontLinger Socket option to false and specifying a
non-zero time-out interval. Close will then block until this data is
sent or until the specified time-out expires. If you set DontLinger to
false and specify a zero time-out interval, Close releases the
connection and automatically discards outgoing queued data.
So either call Shutdown first, or set the DontLinger option to false and set a non-zero timeout.

Detect closed network connection

I've written a number of small programs that communicate via TCP. I'm having endless issues with the system hanging because one program has closed its network connection, and the other end-point somehow fails to notice that it's now disconnected.
I was expecting doing I/O on a TCP connection that has been closed to throw some kind of I/O exception, but instead the program seems to just hang, waiting forever for the other end-point to reply. Obviously if the connection is closed, that reply is never coming. (It doesn't even seem to time out if you leave it for, say, twenty minutes.)
Is there some way I can force the remote end to "see" that I've closed the network connection?
Update: Here is some code...
public sealed class Client
{
public void Connect(IPAddress target)
{
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(ipAddress, 1177);
_stream = new NetworkStream(socket);
}
public void Disconnect()
{
_stream.Close();
}
}
public sealed class Server
{
public void Listen()
{
var listener = new TcpListener(IPAddress.Any, 1177);
listener.Start();
var socket = listener.AcceptSocket();
_stream = new NetworkStream(socket);
...
}
public void Disconnect()
{
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(false);
}
}
When an application closes a socket the right way, it sends a message containing 0 bytes. In some cases you may get a SocketException indicating something went wrong. In a third situation, the remote party is no longer connected (for instance by unplugging the network cable) without any communication between the two parties.
If that last thing happens, you'll have to write data to the socket in order to detect that you can no longer reach the remote party. This is why keep-alive mechanisms were invented - they check every so often whether they can still communicate with the other side.
Seeing the code you posted now: when using NetworkStream the Read operation on it would return a value of 0 (bytes) to indicate that the client has closed the connection.
The documentation is mentions both
"If no data is available for reading, the Read method returns 0."
and
"If the remote host shuts down the connection, and all available data has been received, the Read method completes immediately and return zero bytes."
in the same paragraph. In reality NetworkStream blocks if no data is available for reading while the connection is open.
Hi MathematicalOrchid,
You might find what you are looking for here:
http://blog.stephencleary.com/2009/05/detection-of-half-open-dropped.html
There is some great information there when it comes to working with TCP sockets and detecting half open connections.
You can also refer to this post which seems to have the same solution:
TcpClient communication with server to keep alive connection in c#?
-Dave
You are opening the socket, and assigning it to the stream. At the end of the process, you close the network stream, but not the socket.
For NetworkStream.Close() to close the underlying socket it must have the ownership parameters set to true in the constructor - See MSDN Docs at http://msdn.microsoft.com/en-us/library/te7e60bx.aspx.
This may result in the connection hanging as the underlying socket was not correctly closed.
Change
_stream = new NetworkStream(socket);
To
_stream = new NetworkStream(socket, true);
On a side note, if you do not require a maximum performance for your small app you should try using TCPClient instead - http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient%28v=vs.100%29.aspx. This is a wrapper around socket and it provides connection state checking facilities.

Socket accepting method id like while true

TcpListener tcpserver;
Socket serverSocket = tcpserver.AcceptSocket();
Here 2nd line is like while(true) I mean till it any client gets connected to tcp server
it will not execute any line below it.
What my problem is: I want to accept multiple clients through this tcpserver but based on a flag like if admin_flag is TRUE then accept connection otherwise not. And this flag is going to toggle at any time by different thread.
I write this code:
while (true)
{
if(admin_flag==true)
{
Socket serverSocket = tcpserver.AcceptSocket();
}
else
// do something...
}
when I run it once, client is get connected. but when admin_flag is toggled i.e set to false it is not going in else part this is because the control remains in Accepting state
of socket & not executing other part even if it it while(TRUE).
plz guide??
AcceptSocket is a blocking method call which means that it will block the thread of execution until it can accept an incoming connection. If no connection is established with your listener then the call will continue to block indefinitely.
You would have to for example either stop the listener or switch to accepting connections asynchronously using the non-blocking BeginAcceptSocket or AcceptSocketAsync methods.

TCP port race condition?

I want to start my program multiple times and each instance tries to connect with TCP to the same server port. What I intend is to let the first one connect and the other remaining clients should try to connect to a different port.
I use this code to connect:
TcpClient tcp;
StreamReader streamReader;
StreamWriter streamWriter;
bool success=false;
while (!success) {
try
{
tcp = new TcpClient(Hostname, currentPort);
streamReader = new StreamReader(tcp.GetStream());
streamWriter = new StreamWriter(tcp.GetStream());
success=true;
} catch {
// wait a bit...
}
}
Now the first one will connect succesfully but the second one doesn't get an exception but also isn't connected. How can I determine if a program is really connected? The property tcp.Connected didn't work.
The connected property could sometimes return true, when its not really connected. See msdn TcpClient.Connected:
Because the Connected property only reflects the state of the connection as of the most recent operation, you should attempt to send or receive a message to determine the current state. After the message send fails, this property no longer returns true. Note that this behavior is by design. You cannot reliably test the state of the connection because, in the time between the test and a send/receive, the connection could have been lost. Your code should assume the socket is connected, and gracefully handle failed transmissions
I would suggest you programaticaly check to see if the port is available, instead of relying on exceptions.
And to make it really simple for you, since you can't rely on the Connected flag, people generally suggest you use a pattern found here TcpClient.Connected True, yet not connected:

Proper way to stop listening on a Socket

I have a server that listens for a connection on a socket:
public class Server
{
private Socket _serverSocket;
public Server()
{
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Bind(new IPEndPoint(IPAddress.Any, 1234));
_serverSocket.Listen(1);
}
public void Start()
{
_serverSocket.BeginAccept(HandleAsyncConnectionMethod, null);
}
public void Stop()
{
//????? MAGIC ?????
}
//... rest of code here
}
What is the correct (clean) way to close down the socket?
Is it sufficient to call:
_serverSocket.Disconnect(true);
in the Stop() method? or is there other work that needs to happen to close the connection cleanly?
TCP connection termination correctly involves a four-way handshake. You want both ends to inform the other that they're shutting down and then acknowledge each other's shutdown.
Wikipedia explains the process: http://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_termination
This post explains how to make it happen in C#: http://vadmyst.blogspot.com/2008/04/proper-way-to-close-tcp-socket.html
2 ways to close it properly without exceptions
1) create temporary connecting socket and connect it to listening one so it could have its handler triggered then just finish it with normal EndAccept and after that close both.
2) just Close(0) listening socket which will result in false shot to its callback, if you then look into your listening socket you will see that its state is "closed" and "disposed". This is why calling EndAccept would cause exception. You may just ignore it and do not call EndAccept. Listening socket will go down immediately without timeout.
Since you are listening for incoming TCP connections, you could use System.Net.Sockets.TcpListener which does have a Stop() method. It does not have asynchronous operations though.
The cleanest way to have Accept call break immediately is to call _serverSocket.Dispose();
Any other call to methods in the like of Shutdown or Disconnect will throw an exception.
First, you need to make sure you're keeping track of any client sockets that were created in the process of BeginAccept. Shut those down first using the Socket.Shutdown() and Socket.Close() methods. Once those have all been shut down then do the same on the listening socket itself.
That should handle it...but if you need to make absolutely sure, you could always kill it with fire:
Not for sockets, but same idea applies., which is to close it in every way possible, then finally set the socket to null.
You should use Socket.Shutdown() and then Socket.Close(). Socket.Disconnect() is usually only used if you intend on reconnecting the same socket.

Categories