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
}
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
}