I'm trying to code a client-server communication. So far, i manage to connect in a first thread. A second thread read the socket and a third one check if there is no unexpected disconection from a client.
My problem is that i got a System.ObjectDisposedException when i try to read the socket. If i continue the running of the program (ignoring the exception), the same exception happens when i check if the socket is still connected.
The server is a class with the following fields :
static class Server
{
static ArrayList readList = new ArrayList();
static ArrayList acceptList = new ArrayList();
static public Thread thread1 = new Thread(new ThreadStart(SocketConnector));
static Thread thread2 = new Thread(new ThreadStart(SocketListener));
static Thread thread3 = new Thread(new ThreadStart(SocketClose));
static Thread thread4 = new Thread(new ParameterizedThreadStart(SocketWriter));
readList is used in the socket reader thread (last sample of code in this message) acceptList contains the results of Socket.Accept(). Here is how acceptList is filled.
static void SocketConnector()
{
while (true)
{
sock.Listen(25);
actif = sock.Accept();
if (actif != null)
{
lock (acceptList)
{
acceptList.Add(actif);
Console.WriteLine("IT WORKS");
// that writeline appeared when i try to connect with the client.
}
actif = null;
}
}
Now here is how i check if there wasn't any unexpected disconnection from the client :
static void SocketClose()
{
while (true)
{
for (int i = 0; i < acceptList.Count; ++i)
{
if (((Socket)acceptList[i]).Poll(25, SelectMode.SelectRead) && ((Socket)acceptList[i]).Available == 0)
{
lock (acceptList)
{
((Socket)acceptList[i]).Close();
Console.WriteLine("Client " + ((Socket)acceptList[i]).GetHashCode() + " déconnecté");
acceptList.Remove((Socket)acceptList[i]);
i--;
}
}
}
Thread.Sleep(5);
}
And the last part of code i need to show if how i read my socket.
static void SocketListener()
{
while (true)
{
readList.Clear();
lock (acceptList)
{
for (int i = 0; i < acceptList.Count; i++)
{
readList.Add((Socket)acceptList[i]);
}
}
if (readList.Count > 0)
{
Socket.Select(readList, null, null, 1000);
for (int i = 0; i < readList.Count; i++)
{
if (((Socket)readList[i]).Available > 0)
{
while (((Socket)readList[i]).Available > 0)
{
Console.WriteLine("Debut Deserialisation");
// get the underlying socket for the TcpClient
TcpClient client = new TcpClient();
client.Client = (Socket)readList[i];
NetworkStream ns = client.GetStream();
BinaryReader reader = new BinaryReader(ns);
Message received = new Message();
Console.WriteLine(received.msg);
Console.WriteLine(received.user);
Console.WriteLine(received.targetChatroom);
// Deserialisation
int length = reader.ReadInt32();
byte[] msgArray = reader.ReadBytes(length);
received.msg = Encoding.UTF8.GetString(msgArray);
length = reader.ReadInt32();
msgArray = reader.ReadBytes(length);
received.user = Encoding.UTF8.GetString(msgArray);
length = reader.ReadInt32();
msgArray = reader.ReadBytes(length);
received.targetChatroom = Encoding.UTF8.GetString(msgArray);
ns.Close();
}
}
}
}
}
I realised that maybe my socket was closed by the line ns.Close(), and that cause the error. With ns.Close(), I just attempted to close the stream I created to get the datas from the socket, and not close the socket itself. I tried to remove that ns.Close() line, and the ObjectDisposedException doesn't appear anymore ! However, now i got an OutOfMemoryException at the line :
byte[] msgArray = reader.ReadBytes(length);
in the reading thread. I believe this exception is caused because the stream isn't closed.
EDIT : The OutOfMemoryException comes from code in the client. Problem solved here.
The disconnection detection works, and the deserialization too.
My question is : When should i close that stream ??