Socket remains in CLOSE_WAIT state

G

Guest

I've read many articles on the subject and the majority of them give the same
solution that's in article 821625 on the MSDN website. I'm using the
following code and when a the client disconnects the child socket remains in
the CLOSE_WAIT state. Anyone have any idea what's missing?

----------------------------- Socket Code -----------------------------

namespace Sockets
{
#region Class - SocketClient

public class SocketClient
{
#region Public Delegates

public delegate void MessageReceivedHandler(SocketClient client);
public delegate void ConnectionClosedHandler(SocketClient client);
public delegate void SocketErrorHandler(SocketClient client, Exception e);

#endregion

#region Private Properties and Events

private SocketServer Server;
private NetworkStream Stream;
private TcpClient Client;
private AsyncCallback CallbackReadFunction;
private AsyncCallback CallbackWriteFunction;
private Boolean IsDisposed;

private MessageReceivedHandler OnMessageReceived;
private ConnectionClosedHandler OnConnectionClosed;
private SocketErrorHandler OnSocketError;

#endregion

#region Public Properties

public String IPAddress;
public Int16 Port;
public Object UserData;
public Socket ClientSocket;
public Byte[] RawBuffer;
public Int32 SizeOfRawBuffer;
public Int32 MessageLength;
public StringBuilder StringBuffer;

#endregion

#region Public User Defined Properties

public Boolean IsAvailable;

#endregion

#region Constructor

public SocketClient(Int32 SizeOfRawBuffer, Object UserData,
MessageReceivedHandler MessageHandler, ConnectionClosedHandler CloseHandler,
SocketErrorHandler ErrorHandler)
{
this.SizeOfRawBuffer = SizeOfRawBuffer;
RawBuffer = new Byte[SizeOfRawBuffer];
MessageLength = 0;

this.UserData = UserData;

StringBuffer = new StringBuilder();

OnMessageReceived = MessageHandler;
OnConnectionClosed = CloseHandler;
OnSocketError = ErrorHandler;

CallbackReadFunction = new AsyncCallback(ReceiveComplete);
CallbackWriteFunction = new AsyncCallback(SendComplete);

IsAvailable = true;
IsDisposed = false;
}

public SocketClient(SocketServer ServerSocket, Socket ClientSocket, String
IPAddress, Int16 Port, Int32 SizeOfRawBuffer, Object UserData,
MessageReceivedHandler MessageHandler, ConnectionClosedHandler CloseHandler,
SocketErrorHandler ErrorHandler)
{
Server = ServerSocket;
ClientSocket = ClientSocket;

this.IPAddress = IPAddress;
this.Port = Port;

OnMessageReceived = MessageHandler;
OnConnectionClosed = CloseHandler;
OnSocketError = ErrorHandler;

this.SizeOfRawBuffer = SizeOfRawBuffer;
RawBuffer = new Byte[SizeOfRawBuffer];

this.UserData = UserData;

StringBuffer = new StringBuilder();
Stream = new NetworkStream(ClientSocket);

CallbackReadFunction = new AsyncCallback(ReceiveComplete);
CallbackWriteFunction = new AsyncCallback(SendComplete);

IsAvailable = true;
IsDisposed = false;

ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.ReceiveBuffer, 1048576);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.SendBuffer, 1048576);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.KeepAlive, 1);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.DontLinger, 0);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Tcp,
System.Net.Sockets.SocketOptionName.NoDelay, 1);
}

~SocketClient()
{
if (!IsDisposed)
Dispose();
}

public void Dispose()
{
try
{
IsDisposed = true;
Disconnect();
}

catch
{
}

if (Server != null)
Server.RemoveSocket(this);
}

#endregion

#region Private Methods

private void ReceiveComplete(IAsyncResult ar)
{
try
{
if (Stream.CanRead)
{
MessageLength = Stream.EndRead(ar);

if (MessageLength > 0)
{
try
{
OnMessageReceived(this);
}
catch
{
}

Receive();
}
else
throw new Exception("Shut Down");
}
}
catch
{
try
{
OnConnectionClosed(this);
}
catch
{
}

Dispose();
}
}

private void SendComplete(IAsyncResult ar)
{
try
{
if (Stream.CanWrite)
Stream.EndWrite(ar);
}
catch (Exception)
{
}
}

#endregion

#region Public Methods

public void Connect(String IPAddress, Int16 Port)
{
try
{
if (Stream == null)
{
this.IPAddress = IPAddress;
this.Port = Port;

Client = new TcpClient(IPAddress, Port);
Stream = Client.GetStream();

Client.ReceiveBufferSize = 1048576;
Client.SendBufferSize = 1048576;
Client.NoDelay = true;
Client.LingerState = new System.Net.Sockets.LingerOption(false, 0);

ClientSocket = null;

Receive();
}
}
catch (System.Net.Sockets.SocketException e)
{
throw new Exception(e.Message, e.InnerException);
}
}

public void Disconnect()
{
if (Stream != null)
Stream.Close();

if (Client != null)
Client.Close();

if (ClientSocket != null)
ClientSocket.Close();

ClientSocket = null;
Client = null;
Stream = null;
}

public void Send(String Message)
{
if ((Stream != null) && (Stream.CanWrite))
{
Byte[] RawBuffer = System.Text.Encoding.ASCII.GetBytes(Message);
Stream.BeginWrite(RawBuffer, 0, RawBuffer.GetLength(0),
CallbackWriteFunction, null);
}
else
throw new Exception("Socket Closed");
}

public void Send(Byte[] RawBuffer)
{
if ((Stream != null) && (Stream.CanWrite))
Stream.BeginWrite(RawBuffer, 0, RawBuffer.GetLength(0),
CallbackWriteFunction, null);
else
throw new Exception("Socket Closed");
}

public void Send(Char Character)
{
if ((Stream != null) && (Stream.CanWrite))
{
Byte[] RawBuffer = { Convert.ToByte(Character) };
Stream.BeginWrite(RawBuffer, 0, RawBuffer.GetLength(0),
CallbackWriteFunction, null);
}
else
throw new Exception("Socket Closed");
}

public void Receive()
{
if ((Stream != null) && (Stream.CanRead))
Stream.BeginRead(RawBuffer, 0, SizeOfRawBuffer, CallbackReadFunction,
null);
else
throw new Exception("Socket Closed");
}

#endregion
}

#endregion

#region Class - SocketServer

public class SocketServer
{
#region Public Delagates

public delegate void MessageReceivedHandler(SocketClient client);
public delegate void ConnectionClosedHandler(SocketClient client);
public delegate void SocketErrorHandler(SocketClient client, Exception e);
public delegate void ConnectionAcceptedHandler(SocketClient client);

#endregion

#region Private Properties and Events

private TcpListener Listener;
private Int32 SizeOfRawBuffer;
private Thread AcceptThread;
private Boolean IsDisposed;
private Object SocketListCS;

private MessageReceivedHandler OnMessageReceived;
private ConnectionClosedHandler OnConnectionClosed;
private SocketErrorHandler OnSocketError;
private ConnectionAcceptedHandler OnConnectionAccepted;

#endregion

#region Public Properties

public ArrayList SocketClientList;
public String IPAddress;
public Int16 Port;
public Object UserData;

#endregion

#region Constructor

public SocketServer()
{
SocketListCS = new Object();
IsDisposed = false;
}

~SocketServer()
{
if (!IsDisposed)
Stop();
}

public void Dispose()
{
try
{
IsDisposed = true;

if (AcceptThread != null)
Stop();
}
catch
{
}
}

#endregion

#region Private Methods

private SocketClient AddSocket(SocketClient Client)
{
Monitor.Enter(SocketListCS);

try
{
SocketClientList.Add(Client);
}
catch (Exception e)
{
Monitor.Exit(SocketListCS);

throw e;
}

Monitor.Exit(SocketListCS);

return Client;
}

public void RemoveSocket(SocketClient client)
{
Monitor.Enter(SocketListCS);

try
{
SocketClientList.Remove(client);
}
catch
{
}

Monitor.Exit(SocketListCS);
}

private void Accept_Thread()
{
Socket socket = null;
SocketClient client = null;

try
{
Listener = new TcpListener(Dns.Resolve(IPAddress).AddressList[0], Port);
Listener.Start();

for (;;)
{
try
{
socket = Listener.AcceptSocket();
}
catch (System.Net.Sockets.SocketException e)
{
if (e.ErrorCode != 10004)
{
OnSocketError(null, e);
OnSocketError(null, new Exception("Waiting for new connection 1"));

if (socket != null)
if (socket.Connected)
socket.Close();
}
else
{
OnSocketError(null, new Exception("Shutting Down Accept Thread"));
break;
}
}
catch (Exception e)
{
OnSocketError(null, e);
OnSocketError(null, new Exception("Waiting for new connection 2"));

if (socket != null)
if (socket.Connected)
socket.Close();
}

try
{
if (socket.Connected)
{
client = AddSocket(new SocketClient(this,
socket,
socket.RemoteEndPoint.ToString().Substring(0,15),
Port,
SizeOfRawBuffer,
UserData,
new SocketClient.MessageReceivedHandler(OnMessageReceived),
new SocketClient.ConnectionClosedHandler(OnConnectionClosed),
new SocketClient.SocketErrorHandler(OnSocketError)));

OnConnectionAccepted(client);

client.Receive();
}
}
catch (Exception e)
{
OnSocketError(null, e);
OnSocketError(null, new Exception("Waiting for new connection 3"));
}
}
}
catch (Exception e)
{
OnSocketError(null, e);
OnSocketError(null, new Exception("Shutting Down Accept Thread"));

if (socket != null)
if (socket.Connected)
socket.Close();
}
}

#endregion

#region Public Methods

public void Start(String IPAddress, Int16 Port, Int32 SizeOfRawBuffer,
Object UserData, MessageReceivedHandler MessageHandler,
ConnectionAcceptedHandler AcceptHandler, ConnectionClosedHandler
CloseHandler, SocketErrorHandler ErrorHandler)
{
if (AcceptThread == null)
{
this.IPAddress = IPAddress;
this.Port = Port;

SocketClientList = new ArrayList();

OnMessageReceived = MessageHandler;
OnConnectionAccepted = AcceptHandler;
OnConnectionClosed = CloseHandler;
OnSocketError = ErrorHandler;

this.SizeOfRawBuffer = SizeOfRawBuffer;
this.UserData = UserData;

ThreadStart ThreadDelegate = new ThreadStart(Accept_Thread);
AcceptThread = new Thread(ThreadDelegate);
AcceptThread.Name = "Accept";
AcceptThread.Start();
}
}

public void Stop()
{
if (AcceptThread != null)
{
Listener.Stop();
AcceptThread.Join();
AcceptThread = null;
}

for (int i = 0; i < SocketClientList.Count; ++i)
((SocketClient) SocketClientList).Dispose();

GC.Collect();
GC.WaitForPendingFinalizers();

SocketClientList.Clear();

OnMessageReceived = null;
OnConnectionAccepted = null;
OnConnectionClosed = null;
OnSocketError = null;

SizeOfRawBuffer = 0;
UserData = null;
}

#endregion
}

#endregion
}
 
B

Bob

CLOSE_WAIT is normal, it does not mean the socket is open. It means the
socket is closed but is waiting for any extra data that may be sent to it.
This is used so that a new socket is not created on the same port immeditly
and receive packets from an old connection. There is a default time of (I
think) 120 seconds in this state, which can be changed in the registry.



DreJoh said:
I've read many articles on the subject and the majority of them give the
same
solution that's in article 821625 on the MSDN website. I'm using the
following code and when a the client disconnects the child socket remains
in
the CLOSE_WAIT state. Anyone have any idea what's missing?

----------------------------- Socket Code -----------------------------

namespace Sockets
{
#region Class - SocketClient

public class SocketClient
{
#region Public Delegates

public delegate void MessageReceivedHandler(SocketClient client);
public delegate void ConnectionClosedHandler(SocketClient client);
public delegate void SocketErrorHandler(SocketClient client, Exception e);

#endregion

#region Private Properties and Events

private SocketServer Server;
private NetworkStream Stream;
private TcpClient Client;
private AsyncCallback CallbackReadFunction;
private AsyncCallback CallbackWriteFunction;
private Boolean IsDisposed;

private MessageReceivedHandler OnMessageReceived;
private ConnectionClosedHandler OnConnectionClosed;
private SocketErrorHandler OnSocketError;

#endregion

#region Public Properties

public String IPAddress;
public Int16 Port;
public Object UserData;
public Socket ClientSocket;
public Byte[] RawBuffer;
public Int32 SizeOfRawBuffer;
public Int32 MessageLength;
public StringBuilder StringBuffer;

#endregion

#region Public User Defined Properties

public Boolean IsAvailable;

#endregion

#region Constructor

public SocketClient(Int32 SizeOfRawBuffer, Object UserData,
MessageReceivedHandler MessageHandler, ConnectionClosedHandler
CloseHandler,
SocketErrorHandler ErrorHandler)
{
this.SizeOfRawBuffer = SizeOfRawBuffer;
RawBuffer = new Byte[SizeOfRawBuffer];
MessageLength = 0;

this.UserData = UserData;

StringBuffer = new StringBuilder();

OnMessageReceived = MessageHandler;
OnConnectionClosed = CloseHandler;
OnSocketError = ErrorHandler;

CallbackReadFunction = new AsyncCallback(ReceiveComplete);
CallbackWriteFunction = new AsyncCallback(SendComplete);

IsAvailable = true;
IsDisposed = false;
}

public SocketClient(SocketServer ServerSocket, Socket ClientSocket, String
IPAddress, Int16 Port, Int32 SizeOfRawBuffer, Object UserData,
MessageReceivedHandler MessageHandler, ConnectionClosedHandler
CloseHandler,
SocketErrorHandler ErrorHandler)
{
Server = ServerSocket;
ClientSocket = ClientSocket;

this.IPAddress = IPAddress;
this.Port = Port;

OnMessageReceived = MessageHandler;
OnConnectionClosed = CloseHandler;
OnSocketError = ErrorHandler;

this.SizeOfRawBuffer = SizeOfRawBuffer;
RawBuffer = new Byte[SizeOfRawBuffer];

this.UserData = UserData;

StringBuffer = new StringBuilder();
Stream = new NetworkStream(ClientSocket);

CallbackReadFunction = new AsyncCallback(ReceiveComplete);
CallbackWriteFunction = new AsyncCallback(SendComplete);

IsAvailable = true;
IsDisposed = false;

ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.ReceiveBuffer, 1048576);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.SendBuffer, 1048576);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.KeepAlive, 1);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.DontLinger, 0);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Tcp,
System.Net.Sockets.SocketOptionName.NoDelay, 1);
}

~SocketClient()
{
if (!IsDisposed)
Dispose();
}

public void Dispose()
{
try
{
IsDisposed = true;
Disconnect();
}

catch
{
}

if (Server != null)
Server.RemoveSocket(this);
}

#endregion

#region Private Methods

private void ReceiveComplete(IAsyncResult ar)
{
try
{
if (Stream.CanRead)
{
MessageLength = Stream.EndRead(ar);

if (MessageLength > 0)
{
try
{
OnMessageReceived(this);
}
catch
{
}

Receive();
}
else
throw new Exception("Shut Down");
}
}
catch
{
try
{
OnConnectionClosed(this);
}
catch
{
}

Dispose();
}
}

private void SendComplete(IAsyncResult ar)
{
try
{
if (Stream.CanWrite)
Stream.EndWrite(ar);
}
catch (Exception)
{
}
}

#endregion

#region Public Methods

public void Connect(String IPAddress, Int16 Port)
{
try
{
if (Stream == null)
{
this.IPAddress = IPAddress;
this.Port = Port;

Client = new TcpClient(IPAddress, Port);
Stream = Client.GetStream();

Client.ReceiveBufferSize = 1048576;
Client.SendBufferSize = 1048576;
Client.NoDelay = true;
Client.LingerState = new System.Net.Sockets.LingerOption(false, 0);

ClientSocket = null;

Receive();
}
}
catch (System.Net.Sockets.SocketException e)
{
throw new Exception(e.Message, e.InnerException);
}
}

public void Disconnect()
{
if (Stream != null)
Stream.Close();

if (Client != null)
Client.Close();

if (ClientSocket != null)
ClientSocket.Close();

ClientSocket = null;
Client = null;
Stream = null;
}

public void Send(String Message)
{
if ((Stream != null) && (Stream.CanWrite))
{
Byte[] RawBuffer = System.Text.Encoding.ASCII.GetBytes(Message);
Stream.BeginWrite(RawBuffer, 0, RawBuffer.GetLength(0),
CallbackWriteFunction, null);
}
else
throw new Exception("Socket Closed");
}

public void Send(Byte[] RawBuffer)
{
if ((Stream != null) && (Stream.CanWrite))
Stream.BeginWrite(RawBuffer, 0, RawBuffer.GetLength(0),
CallbackWriteFunction, null);
else
throw new Exception("Socket Closed");
}

public void Send(Char Character)
{
if ((Stream != null) && (Stream.CanWrite))
{
Byte[] RawBuffer = { Convert.ToByte(Character) };
Stream.BeginWrite(RawBuffer, 0, RawBuffer.GetLength(0),
CallbackWriteFunction, null);
}
else
throw new Exception("Socket Closed");
}

public void Receive()
{
if ((Stream != null) && (Stream.CanRead))
Stream.BeginRead(RawBuffer, 0, SizeOfRawBuffer, CallbackReadFunction,
null);
else
throw new Exception("Socket Closed");
}

#endregion
}

#endregion

#region Class - SocketServer

public class SocketServer
{
#region Public Delagates

public delegate void MessageReceivedHandler(SocketClient client);
public delegate void ConnectionClosedHandler(SocketClient client);
public delegate void SocketErrorHandler(SocketClient client, Exception e);
public delegate void ConnectionAcceptedHandler(SocketClient client);

#endregion

#region Private Properties and Events

private TcpListener Listener;
private Int32 SizeOfRawBuffer;
private Thread AcceptThread;
private Boolean IsDisposed;
private Object SocketListCS;

private MessageReceivedHandler OnMessageReceived;
private ConnectionClosedHandler OnConnectionClosed;
private SocketErrorHandler OnSocketError;
private ConnectionAcceptedHandler OnConnectionAccepted;

#endregion

#region Public Properties

public ArrayList SocketClientList;
public String IPAddress;
public Int16 Port;
public Object UserData;

#endregion

#region Constructor

public SocketServer()
{
SocketListCS = new Object();
IsDisposed = false;
}

~SocketServer()
{
if (!IsDisposed)
Stop();
}

public void Dispose()
{
try
{
IsDisposed = true;

if (AcceptThread != null)
Stop();
}
catch
{
}
}

#endregion

#region Private Methods

private SocketClient AddSocket(SocketClient Client)
{
Monitor.Enter(SocketListCS);

try
{
SocketClientList.Add(Client);
}
catch (Exception e)
{
Monitor.Exit(SocketListCS);

throw e;
}

Monitor.Exit(SocketListCS);

return Client;
}

public void RemoveSocket(SocketClient client)
{
Monitor.Enter(SocketListCS);

try
{
SocketClientList.Remove(client);
}
catch
{
}

Monitor.Exit(SocketListCS);
}

private void Accept_Thread()
{
Socket socket = null;
SocketClient client = null;

try
{
Listener = new TcpListener(Dns.Resolve(IPAddress).AddressList[0], Port);
Listener.Start();

for (;;)
{
try
{
socket = Listener.AcceptSocket();
}
catch (System.Net.Sockets.SocketException e)
{
if (e.ErrorCode != 10004)
{
OnSocketError(null, e);
OnSocketError(null, new Exception("Waiting for new connection 1"));

if (socket != null)
if (socket.Connected)
socket.Close();
}
else
{
OnSocketError(null, new Exception("Shutting Down Accept Thread"));
break;
}
}
catch (Exception e)
{
OnSocketError(null, e);
OnSocketError(null, new Exception("Waiting for new connection 2"));

if (socket != null)
if (socket.Connected)
socket.Close();
}

try
{
if (socket.Connected)
{
client = AddSocket(new SocketClient(this,
socket,
socket.RemoteEndPoint.ToString().Substring(0,15),
Port,
SizeOfRawBuffer,
UserData,
new SocketClient.MessageReceivedHandler(OnMessageReceived),
new SocketClient.ConnectionClosedHandler(OnConnectionClosed),
new SocketClient.SocketErrorHandler(OnSocketError)));

OnConnectionAccepted(client);

client.Receive();
}
}
catch (Exception e)
{
OnSocketError(null, e);
OnSocketError(null, new Exception("Waiting for new connection 3"));
}
}
}
catch (Exception e)
{
OnSocketError(null, e);
OnSocketError(null, new Exception("Shutting Down Accept Thread"));

if (socket != null)
if (socket.Connected)
socket.Close();
}
}

#endregion

#region Public Methods

public void Start(String IPAddress, Int16 Port, Int32 SizeOfRawBuffer,
Object UserData, MessageReceivedHandler MessageHandler,
ConnectionAcceptedHandler AcceptHandler, ConnectionClosedHandler
CloseHandler, SocketErrorHandler ErrorHandler)
{
if (AcceptThread == null)
{
this.IPAddress = IPAddress;
this.Port = Port;

SocketClientList = new ArrayList();

OnMessageReceived = MessageHandler;
OnConnectionAccepted = AcceptHandler;
OnConnectionClosed = CloseHandler;
OnSocketError = ErrorHandler;

this.SizeOfRawBuffer = SizeOfRawBuffer;
this.UserData = UserData;

ThreadStart ThreadDelegate = new ThreadStart(Accept_Thread);
AcceptThread = new Thread(ThreadDelegate);
AcceptThread.Name = "Accept";
AcceptThread.Start();
}
}

public void Stop()
{
if (AcceptThread != null)
{
Listener.Stop();
AcceptThread.Join();
AcceptThread = null;
}

for (int i = 0; i < SocketClientList.Count; ++i)
((SocketClient) SocketClientList).Dispose();

GC.Collect();
GC.WaitForPendingFinalizers();

SocketClientList.Clear();

OnMessageReceived = null;
OnConnectionAccepted = null;
OnConnectionClosed = null;
OnSocketError = null;

SizeOfRawBuffer = 0;
UserData = null;
}

#endregion
}

#endregion
}
 
G

Guest

The problem is that the CLOSE_WAIT states never go away and they build up
over time (hours). I have to shutdown the socket server after a few hours to
clear them off.

I reduced the time to KeepAlive, but it didn't help. Are there any other
registry parameters I might need to set?

Bob said:
CLOSE_WAIT is normal, it does not mean the socket is open. It means the
socket is closed but is waiting for any extra data that may be sent to it.
This is used so that a new socket is not created on the same port immeditly
and receive packets from an old connection. There is a default time of (I
think) 120 seconds in this state, which can be changed in the registry.



DreJoh said:
I've read many articles on the subject and the majority of them give the
same
solution that's in article 821625 on the MSDN website. I'm using the
following code and when a the client disconnects the child socket remains
in
the CLOSE_WAIT state. Anyone have any idea what's missing?

----------------------------- Socket Code -----------------------------

namespace Sockets
{
#region Class - SocketClient

public class SocketClient
{
#region Public Delegates

public delegate void MessageReceivedHandler(SocketClient client);
public delegate void ConnectionClosedHandler(SocketClient client);
public delegate void SocketErrorHandler(SocketClient client, Exception e);

#endregion

#region Private Properties and Events

private SocketServer Server;
private NetworkStream Stream;
private TcpClient Client;
private AsyncCallback CallbackReadFunction;
private AsyncCallback CallbackWriteFunction;
private Boolean IsDisposed;

private MessageReceivedHandler OnMessageReceived;
private ConnectionClosedHandler OnConnectionClosed;
private SocketErrorHandler OnSocketError;

#endregion

#region Public Properties

public String IPAddress;
public Int16 Port;
public Object UserData;
public Socket ClientSocket;
public Byte[] RawBuffer;
public Int32 SizeOfRawBuffer;
public Int32 MessageLength;
public StringBuilder StringBuffer;

#endregion

#region Public User Defined Properties

public Boolean IsAvailable;

#endregion

#region Constructor

public SocketClient(Int32 SizeOfRawBuffer, Object UserData,
MessageReceivedHandler MessageHandler, ConnectionClosedHandler
CloseHandler,
SocketErrorHandler ErrorHandler)
{
this.SizeOfRawBuffer = SizeOfRawBuffer;
RawBuffer = new Byte[SizeOfRawBuffer];
MessageLength = 0;

this.UserData = UserData;

StringBuffer = new StringBuilder();

OnMessageReceived = MessageHandler;
OnConnectionClosed = CloseHandler;
OnSocketError = ErrorHandler;

CallbackReadFunction = new AsyncCallback(ReceiveComplete);
CallbackWriteFunction = new AsyncCallback(SendComplete);

IsAvailable = true;
IsDisposed = false;
}

public SocketClient(SocketServer ServerSocket, Socket ClientSocket, String
IPAddress, Int16 Port, Int32 SizeOfRawBuffer, Object UserData,
MessageReceivedHandler MessageHandler, ConnectionClosedHandler
CloseHandler,
SocketErrorHandler ErrorHandler)
{
Server = ServerSocket;
ClientSocket = ClientSocket;

this.IPAddress = IPAddress;
this.Port = Port;

OnMessageReceived = MessageHandler;
OnConnectionClosed = CloseHandler;
OnSocketError = ErrorHandler;

this.SizeOfRawBuffer = SizeOfRawBuffer;
RawBuffer = new Byte[SizeOfRawBuffer];

this.UserData = UserData;

StringBuffer = new StringBuilder();
Stream = new NetworkStream(ClientSocket);

CallbackReadFunction = new AsyncCallback(ReceiveComplete);
CallbackWriteFunction = new AsyncCallback(SendComplete);

IsAvailable = true;
IsDisposed = false;

ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.ReceiveBuffer, 1048576);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.SendBuffer, 1048576);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.KeepAlive, 1);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.DontLinger, 0);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Tcp,
System.Net.Sockets.SocketOptionName.NoDelay, 1);
}

~SocketClient()
{
if (!IsDisposed)
Dispose();
}

public void Dispose()
{
try
{
IsDisposed = true;
Disconnect();
}

catch
{
}

if (Server != null)
Server.RemoveSocket(this);
}

#endregion

#region Private Methods

private void ReceiveComplete(IAsyncResult ar)
{
try
{
if (Stream.CanRead)
{
MessageLength = Stream.EndRead(ar);

if (MessageLength > 0)
{
try
{
OnMessageReceived(this);
}
catch
{
}

Receive();
}
else
throw new Exception("Shut Down");
}
}
catch
{
try
{
OnConnectionClosed(this);
}
catch
{
}

Dispose();
}
}

private void SendComplete(IAsyncResult ar)
{
try
{
if (Stream.CanWrite)
Stream.EndWrite(ar);
}
catch (Exception)
{
}
}

#endregion

#region Public Methods

public void Connect(String IPAddress, Int16 Port)
{
try
{
if (Stream == null)
{
this.IPAddress = IPAddress;
this.Port = Port;

Client = new TcpClient(IPAddress, Port);
Stream = Client.GetStream();

Client.ReceiveBufferSize = 1048576;
Client.SendBufferSize = 1048576;
Client.NoDelay = true;
Client.LingerState = new System.Net.Sockets.LingerOption(false, 0);

ClientSocket = null;

Receive();
}
}
catch (System.Net.Sockets.SocketException e)
{
throw new Exception(e.Message, e.InnerException);
}
}

public void Disconnect()
{
if (Stream != null)
Stream.Close();

if (Client != null)
Client.Close();

if (ClientSocket != null)
ClientSocket.Close();

ClientSocket = null;
Client = null;
Stream = null;
}

public void Send(String Message)
{
if ((Stream != null) && (Stream.CanWrite))
{
Byte[] RawBuffer = System.Text.Encoding.ASCII.GetBytes(Message);
Stream.BeginWrite(RawBuffer, 0, RawBuffer.GetLength(0),
CallbackWriteFunction, null);
}
else
throw new Exception("Socket Closed");
}

public void Send(Byte[] RawBuffer)
{
if ((Stream != null) && (Stream.CanWrite))
Stream.BeginWrite(RawBuffer, 0, RawBuffer.GetLength(0),
CallbackWriteFunction, null);
else
throw new Exception("Socket Closed");
}

public void Send(Char Character)
{
if ((Stream != null) && (Stream.CanWrite))
{
Byte[] RawBuffer = { Convert.ToByte(Character) };
Stream.BeginWrite(RawBuffer, 0, RawBuffer.GetLength(0),
CallbackWriteFunction, null);
}
else
throw new Exception("Socket Closed");
}

public void Receive()
{
if ((Stream != null) && (Stream.CanRead))
Stream.BeginRead(RawBuffer, 0, SizeOfRawBuffer, CallbackReadFunction,
null);
else
throw new Exception("Socket Closed");
}
 
B

Bob

Normally if the socket is not closed correctly it stays in the FIN_WAIT_X
state not TIME_WAIT. But if you are using all the ports up because you are
creating a lot of connections very fast then you can increase the number of
allowed user ports in the registry. By default this is 5000 (Minus 1024
reserved ports.) This can be increased to 65535. Search MSDN for
MaxUserPort and it will give more information on increasing this value.


DreJoh said:
The problem is that the CLOSE_WAIT states never go away and they build up
over time (hours). I have to shutdown the socket server after a few hours
to
clear them off.

I reduced the time to KeepAlive, but it didn't help. Are there any other
registry parameters I might need to set?

Bob said:
CLOSE_WAIT is normal, it does not mean the socket is open. It means the
socket is closed but is waiting for any extra data that may be sent to
it.
This is used so that a new socket is not created on the same port
immeditly
and receive packets from an old connection. There is a default time of (I
think) 120 seconds in this state, which can be changed in the registry.



DreJoh said:
I've read many articles on the subject and the majority of them give
the
same
solution that's in article 821625 on the MSDN website. I'm using the
following code and when a the client disconnects the child socket
remains
in
the CLOSE_WAIT state. Anyone have any idea what's missing?

----------------------------- Socket Code -----------------------------

namespace Sockets
{
#region Class - SocketClient

public class SocketClient
{
#region Public Delegates

public delegate void MessageReceivedHandler(SocketClient client);
public delegate void ConnectionClosedHandler(SocketClient client);
public delegate void SocketErrorHandler(SocketClient client, Exception
e);

#endregion

#region Private Properties and Events

private SocketServer Server;
private NetworkStream Stream;
private TcpClient Client;
private AsyncCallback CallbackReadFunction;
private AsyncCallback CallbackWriteFunction;
private Boolean IsDisposed;

private MessageReceivedHandler OnMessageReceived;
private ConnectionClosedHandler OnConnectionClosed;
private SocketErrorHandler OnSocketError;

#endregion

#region Public Properties

public String IPAddress;
public Int16 Port;
public Object UserData;
public Socket ClientSocket;
public Byte[] RawBuffer;
public Int32 SizeOfRawBuffer;
public Int32 MessageLength;
public StringBuilder StringBuffer;

#endregion

#region Public User Defined Properties

public Boolean IsAvailable;

#endregion

#region Constructor

public SocketClient(Int32 SizeOfRawBuffer, Object UserData,
MessageReceivedHandler MessageHandler, ConnectionClosedHandler
CloseHandler,
SocketErrorHandler ErrorHandler)
{
this.SizeOfRawBuffer = SizeOfRawBuffer;
RawBuffer = new Byte[SizeOfRawBuffer];
MessageLength = 0;

this.UserData = UserData;

StringBuffer = new StringBuilder();

OnMessageReceived = MessageHandler;
OnConnectionClosed = CloseHandler;
OnSocketError = ErrorHandler;

CallbackReadFunction = new AsyncCallback(ReceiveComplete);
CallbackWriteFunction = new AsyncCallback(SendComplete);

IsAvailable = true;
IsDisposed = false;
}

public SocketClient(SocketServer ServerSocket, Socket ClientSocket,
String
IPAddress, Int16 Port, Int32 SizeOfRawBuffer, Object UserData,
MessageReceivedHandler MessageHandler, ConnectionClosedHandler
CloseHandler,
SocketErrorHandler ErrorHandler)
{
Server = ServerSocket;
ClientSocket = ClientSocket;

this.IPAddress = IPAddress;
this.Port = Port;

OnMessageReceived = MessageHandler;
OnConnectionClosed = CloseHandler;
OnSocketError = ErrorHandler;

this.SizeOfRawBuffer = SizeOfRawBuffer;
RawBuffer = new Byte[SizeOfRawBuffer];

this.UserData = UserData;

StringBuffer = new StringBuilder();
Stream = new NetworkStream(ClientSocket);

CallbackReadFunction = new AsyncCallback(ReceiveComplete);
CallbackWriteFunction = new AsyncCallback(SendComplete);

IsAvailable = true;
IsDisposed = false;

ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.ReceiveBuffer, 1048576);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.SendBuffer, 1048576);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.KeepAlive, 1);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.DontLinger, 0);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Tcp,
System.Net.Sockets.SocketOptionName.NoDelay, 1);
}

~SocketClient()
{
if (!IsDisposed)
Dispose();
}

public void Dispose()
{
try
{
IsDisposed = true;
Disconnect();
}

catch
{
}

if (Server != null)
Server.RemoveSocket(this);
}

#endregion

#region Private Methods

private void ReceiveComplete(IAsyncResult ar)
{
try
{
if (Stream.CanRead)
{
MessageLength = Stream.EndRead(ar);

if (MessageLength > 0)
{
try
{
OnMessageReceived(this);
}
catch
{
}

Receive();
}
else
throw new Exception("Shut Down");
}
}
catch
{
try
{
OnConnectionClosed(this);
}
catch
{
}

Dispose();
}
}

private void SendComplete(IAsyncResult ar)
{
try
{
if (Stream.CanWrite)
Stream.EndWrite(ar);
}
catch (Exception)
{
}
}

#endregion

#region Public Methods

public void Connect(String IPAddress, Int16 Port)
{
try
{
if (Stream == null)
{
this.IPAddress = IPAddress;
this.Port = Port;

Client = new TcpClient(IPAddress, Port);
Stream = Client.GetStream();

Client.ReceiveBufferSize = 1048576;
Client.SendBufferSize = 1048576;
Client.NoDelay = true;
Client.LingerState = new System.Net.Sockets.LingerOption(false,
0);

ClientSocket = null;

Receive();
}
}
catch (System.Net.Sockets.SocketException e)
{
throw new Exception(e.Message, e.InnerException);
}
}

public void Disconnect()
{
if (Stream != null)
Stream.Close();

if (Client != null)
Client.Close();

if (ClientSocket != null)
ClientSocket.Close();

ClientSocket = null;
Client = null;
Stream = null;
}

public void Send(String Message)
{
if ((Stream != null) && (Stream.CanWrite))
{
Byte[] RawBuffer = System.Text.Encoding.ASCII.GetBytes(Message);
Stream.BeginWrite(RawBuffer, 0, RawBuffer.GetLength(0),
CallbackWriteFunction, null);
}
else
throw new Exception("Socket Closed");
}

public void Send(Byte[] RawBuffer)
{
if ((Stream != null) && (Stream.CanWrite))
Stream.BeginWrite(RawBuffer, 0, RawBuffer.GetLength(0),
CallbackWriteFunction, null);
else
throw new Exception("Socket Closed");
}

public void Send(Char Character)
{
if ((Stream != null) && (Stream.CanWrite))
{
Byte[] RawBuffer = { Convert.ToByte(Character) };
Stream.BeginWrite(RawBuffer, 0, RawBuffer.GetLength(0),
CallbackWriteFunction, null);
}
else
throw new Exception("Socket Closed");
}

public void Receive()
{
if ((Stream != null) && (Stream.CanRead))
Stream.BeginRead(RawBuffer, 0, SizeOfRawBuffer, CallbackReadFunction,
null);
else
throw new Exception("Socket Closed");
}
 
G

Guest

I have attempted to tune with several registry settings including
MaxUserPort. I set it to 32768. But, I'm not having a problem with
connections coming in too fast. In, fact as I am writing I have one
CLOSE_WAIT state on the machine that has been there for over 6 hours. I will
go away only when I shutdown the socket. This is not a production evironment.
I'm testing and trying to solve this problem on a test machine.

I don't have a sniffer, so I wrote a batch file that loops with no delay and
redirects output to a file. The command in the loop is netstat -na -p tcpCLOSE_WAIT and FIN_WAIT_2. That's with the batch file and/or done manually.

Hey, after six hours my CLOSE_WAIT has gone away. I guess I can live with
that until I figure something else out.

Thanks Bob

Bob said:
Normally if the socket is not closed correctly it stays in the FIN_WAIT_X
state not TIME_WAIT. But if you are using all the ports up because you are
creating a lot of connections very fast then you can increase the number of
allowed user ports in the registry. By default this is 5000 (Minus 1024
reserved ports.) This can be increased to 65535. Search MSDN for
MaxUserPort and it will give more information on increasing this value.


DreJoh said:
The problem is that the CLOSE_WAIT states never go away and they build up
over time (hours). I have to shutdown the socket server after a few hours
to
clear them off.

I reduced the time to KeepAlive, but it didn't help. Are there any other
registry parameters I might need to set?

Bob said:
CLOSE_WAIT is normal, it does not mean the socket is open. It means the
socket is closed but is waiting for any extra data that may be sent to
it.
This is used so that a new socket is not created on the same port
immeditly
and receive packets from an old connection. There is a default time of (I
think) 120 seconds in this state, which can be changed in the registry.



I've read many articles on the subject and the majority of them give
the
same
solution that's in article 821625 on the MSDN website. I'm using the
following code and when a the client disconnects the child socket
remains
in
the CLOSE_WAIT state. Anyone have any idea what's missing?

----------------------------- Socket Code -----------------------------

namespace Sockets
{
#region Class - SocketClient

public class SocketClient
{
#region Public Delegates

public delegate void MessageReceivedHandler(SocketClient client);
public delegate void ConnectionClosedHandler(SocketClient client);
public delegate void SocketErrorHandler(SocketClient client, Exception
e);

#endregion

#region Private Properties and Events

private SocketServer Server;
private NetworkStream Stream;
private TcpClient Client;
private AsyncCallback CallbackReadFunction;
private AsyncCallback CallbackWriteFunction;
private Boolean IsDisposed;

private MessageReceivedHandler OnMessageReceived;
private ConnectionClosedHandler OnConnectionClosed;
private SocketErrorHandler OnSocketError;

#endregion

#region Public Properties

public String IPAddress;
public Int16 Port;
public Object UserData;
public Socket ClientSocket;
public Byte[] RawBuffer;
public Int32 SizeOfRawBuffer;
public Int32 MessageLength;
public StringBuilder StringBuffer;

#endregion

#region Public User Defined Properties

public Boolean IsAvailable;

#endregion

#region Constructor

public SocketClient(Int32 SizeOfRawBuffer, Object UserData,
MessageReceivedHandler MessageHandler, ConnectionClosedHandler
CloseHandler,
SocketErrorHandler ErrorHandler)
{
this.SizeOfRawBuffer = SizeOfRawBuffer;
RawBuffer = new Byte[SizeOfRawBuffer];
MessageLength = 0;

this.UserData = UserData;

StringBuffer = new StringBuilder();

OnMessageReceived = MessageHandler;
OnConnectionClosed = CloseHandler;
OnSocketError = ErrorHandler;

CallbackReadFunction = new AsyncCallback(ReceiveComplete);
CallbackWriteFunction = new AsyncCallback(SendComplete);

IsAvailable = true;
IsDisposed = false;
}

public SocketClient(SocketServer ServerSocket, Socket ClientSocket,
String
IPAddress, Int16 Port, Int32 SizeOfRawBuffer, Object UserData,
MessageReceivedHandler MessageHandler, ConnectionClosedHandler
CloseHandler,
SocketErrorHandler ErrorHandler)
{
Server = ServerSocket;
ClientSocket = ClientSocket;

this.IPAddress = IPAddress;
this.Port = Port;

OnMessageReceived = MessageHandler;
OnConnectionClosed = CloseHandler;
OnSocketError = ErrorHandler;

this.SizeOfRawBuffer = SizeOfRawBuffer;
RawBuffer = new Byte[SizeOfRawBuffer];

this.UserData = UserData;

StringBuffer = new StringBuilder();
Stream = new NetworkStream(ClientSocket);

CallbackReadFunction = new AsyncCallback(ReceiveComplete);
CallbackWriteFunction = new AsyncCallback(SendComplete);

IsAvailable = true;
IsDisposed = false;

ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.ReceiveBuffer, 1048576);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.SendBuffer, 1048576);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.KeepAlive, 1);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,
System.Net.Sockets.SocketOptionName.DontLinger, 0);
ClientSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Tcp,
System.Net.Sockets.SocketOptionName.NoDelay, 1);
}

~SocketClient()
{
if (!IsDisposed)
Dispose();
}

public void Dispose()
{
try
{
IsDisposed = true;
Disconnect();
}

catch
{
}

if (Server != null)
Server.RemoveSocket(this);
}

#endregion

#region Private Methods

private void ReceiveComplete(IAsyncResult ar)
{
try
{
if (Stream.CanRead)
{
MessageLength = Stream.EndRead(ar);

if (MessageLength > 0)
{
try
{
OnMessageReceived(this);
}
catch
{
}

Receive();
}
else
throw new Exception("Shut Down");
}
}
catch
{
try
{
OnConnectionClosed(this);
}
catch
{
}

Dispose();
}
}

private void SendComplete(IAsyncResult ar)
{
try
{
if (Stream.CanWrite)
Stream.EndWrite(ar);
}
catch (Exception)
{
}
}

#endregion

#region Public Methods

public void Connect(String IPAddress, Int16 Port)
{
try
{
if (Stream == null)
{
this.IPAddress = IPAddress;
this.Port = Port;

Client = new TcpClient(IPAddress, Port);
Stream = Client.GetStream();

Client.ReceiveBufferSize = 1048576;
Client.SendBufferSize = 1048576;
Client.NoDelay = true;
Client.LingerState = new System.Net.Sockets.LingerOption(false,
0);

ClientSocket = null;

Receive();
}
}
catch (System.Net.Sockets.SocketException e)
{
throw new Exception(e.Message, e.InnerException);
}
}

public void Disconnect()
{
if (Stream != null)
Stream.Close();

if (Client != null)
Client.Close();

if (ClientSocket != null)
ClientSocket.Close();

ClientSocket = null;
Client = null;
Stream = null;
}

public void Send(String Message)
{
if ((Stream != null) && (Stream.CanWrite))
{
Byte[] RawBuffer = System.Text.Encoding.ASCII.GetBytes(Message);
Stream.BeginWrite(RawBuffer, 0, RawBuffer.GetLength(0),
CallbackWriteFunction, null);
}
else
throw new Exception("Socket Closed");
}

public void Send(Byte[] RawBuffer)
{
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top