Reputation: 403
I'm hoping someone can tell me why I'm getting an object disposed exception in my tcpListener/tcpClient code.
In the acceptConnections and connectToServer methods I use the keepalive method to tell me when I get disconnected and it works fine.
However, if I uncomment the for loop for my sendMsg method I will get an ObjectDisposedException on the server and an IOException on the client.
The tcpClient.getStream()'s NetworkStream in SendMsg seems to be the issue but I am unsure why it would get a disposed stream. Do I need 2 threads to work with it?
static void Main(string[] args)
{
server.Listen();
server.AcceptConnections();
client.ConnectToServer();
//for (int i = 0; i < 5; i++) {
// Thread.Sleep(3000);
// server.SendMsg("SENT MSG");
//}
Console.ReadLine();
}
public async void SendMsg(String message) {
try {
NetworkStream networkStream = tcpClient.GetStream();
using (var writer = new StreamWriter(networkStream)) {
await writer.WriteLineAsync(message);
Console.WriteLine("msg sent");
};
} catch (Exception e) {
}
}
private async void KeepAlive(TcpClient tcpClient) {
bool clientConnected = true;
using (NetworkStream networkStream = tcpClient.GetStream())
using (var reader = new StreamReader(networkStream))
using (var writer = new StreamWriter(networkStream)) {
writer.AutoFlush = true;
char keepalive = '0';
while (clientConnected) {
try {
await writer.WriteLineAsync(keepalive);
string dataFromClient = await reader.ReadLineAsync();
Console.WriteLine("Server: " + dataFromClient);
Thread.Sleep(500);
} catch (IOException e){
} catch(ObjectDisposedException e) {
clientConnected = false;
clientsConnected--;
} catch (Exception e){
}
}
}
}
EDIT: posting my AcceptConnections method as well
public async void AcceptConnections() {
while (true) {
while (clientsConnected <= maxConnections) {
try {
tcpClient = await tcpListener.AcceptTcpClientAsync();
KeepAlive(tcpClient);
} catch (Exception e) {
Console.WriteLine("TOP EXCEPTION :: " + e);
}
clientsConnected++;
Console.WriteLine("SERVER Clients connected: " + clientsConnected);
}
}
}
Upvotes: 1
Views: 1226
Reputation: 1062770
Your SendMsg
method uses using
on a StreamWriter
. The default for a StreamWriter
is to cascade the dispose, so this will close the NetworkStream
. If that isn't your intent, you need to pass leaveOpen: true
to the constructor overload.
Frankly though, there's no reason to use StreamWriter
here - I would suggest dealing with the Stream
and Encoding
APIs directly. One advantage of StreamWriter
is that internally it might re-use a buffer for the byte[]
work, but that "advantage" is moot if you're only using it for one Write
before disposing it, and can be readily achieved with a buffer pool.
Upvotes: 1