c# NetworkStream 处理过 tcp/ip
c# NetworkStream disposed over tcp/ip
我希望有人能告诉我为什么我的 tcpListener/tcpClient 代码中出现对象处置异常。
在 acceptConnections 和 connectToServer 方法中,我使用 keepalive 方法在断开连接时告诉我它工作正常。
但是,如果我取消注释我的 sendMsg 方法的 for 循环,我将在服务器上得到一个 ObjectDisposedException,在客户端上得到一个 IOException。
SendMsg 中 tcpClient.getStream() 的 NetworkStream 似乎是问题所在,但我不确定为什么它会得到处置流。我需要 2 个线程才能使用它吗?
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){
}
}
}
}
编辑:同时发布我的 AcceptConnections 方法
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);
}
}
}
您的 SendMsg
方法在 StreamWriter
上使用 using
。 StreamWriter
的 默认 是级联处置,因此这将关闭 NetworkStream
。如果这不是您的意图,您需要将 leaveOpen: true
传递给 constructor overload。
坦率地说,没有理由在这里使用 StreamWriter
- 我建议直接处理 Stream
和 Encoding
API。 StreamWriter
的一个优点是在内部它可能会为 byte[]
工作重新使用一个缓冲区,但是如果你只将它用于一个 Write
,那么 "advantage" 是没有实际意义的在处理它之前,可以通过缓冲池轻松实现。
我希望有人能告诉我为什么我的 tcpListener/tcpClient 代码中出现对象处置异常。
在 acceptConnections 和 connectToServer 方法中,我使用 keepalive 方法在断开连接时告诉我它工作正常。
但是,如果我取消注释我的 sendMsg 方法的 for 循环,我将在服务器上得到一个 ObjectDisposedException,在客户端上得到一个 IOException。
SendMsg 中 tcpClient.getStream() 的 NetworkStream 似乎是问题所在,但我不确定为什么它会得到处置流。我需要 2 个线程才能使用它吗?
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){
}
}
}
}
编辑:同时发布我的 AcceptConnections 方法
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);
}
}
}
您的 SendMsg
方法在 StreamWriter
上使用 using
。 StreamWriter
的 默认 是级联处置,因此这将关闭 NetworkStream
。如果这不是您的意图,您需要将 leaveOpen: true
传递给 constructor overload。
坦率地说,没有理由在这里使用 StreamWriter
- 我建议直接处理 Stream
和 Encoding
API。 StreamWriter
的一个优点是在内部它可能会为 byte[]
工作重新使用一个缓冲区,但是如果你只将它用于一个 Write
,那么 "advantage" 是没有实际意义的在处理它之前,可以通过缓冲池轻松实现。