通过tcp/ip处理的c#网络流

通过tcp/ip处理的c#网络流,c#,tcp,tcplistener,networkstream,objectdisposedexception,C#,Tcp,Tcplistener,Networkstream,Objectdisposedexception,我希望有人能告诉我为什么在我的tcpListener/tcpClient代码中出现对象处理异常 在acceptConnections和connectToServer方法中,我使用keepalive方法来告诉我何时断开连接,并且工作正常 但是,如果我取消对sendMsg方法的for循环的注释,我将在服务器上得到一个ObjectDisposedException,在客户端得到一个IOException SendMsg中tcpClient.getStream()的NetworkStream似乎是问题所

我希望有人能告诉我为什么在我的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){
                }
            }
        }
    }
static void Main(字符串[]args)
{
server.Listen();
AcceptConnections();
client.ConnectToServer();
//对于(int i=0;i<5;i++){
//睡眠(3000);
//SendMsg(“sentmsg”);
//}
Console.ReadLine();
}
公共异步void SendMsg(字符串消息){
试一试{
NetworkStream NetworkStream=tcpClient.GetStream();
使用(var writer=newstreamwriter(networkStream)){
等待writer.WriteLineAsync(消息);
Console.WriteLine(“已发送消息”);
};
}捕获(例外e){
}
}
专用异步void KeepAlive(TcpClient TcpClient){
bool clientConnected=true;
使用(NetworkStream NetworkStream=tcpClient.GetStream())
使用(var reader=newstreamreader(networkStream))
使用(var writer=newstreamwriter(networkStream)){
writer.AutoFlush=true;
char keepalive='0';
while(客户端连接){
试一试{
等待编写器。WriteLineAsync(keepalive);
字符串dataFromClient=wait reader.readlinesync();
Console.WriteLine(“服务器:”+dataFromClient);
睡眠(500);
}捕获(IOE异常){
}捕获(ObjectDisposedException e){
clientConnected=false;
客户连接--;
}捕获(例外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);
            }
        }
    }
public异步void AcceptConnections(){
while(true){

while(clients)connected您的
SendMsg
方法在
StreamWriter
上使用
using
StreamWriter
的默认设置是级联dispose,因此这将关闭
NetworkStream
。如果这不是您的意图,您需要将
leaveOpen:true
传递到


坦率地说,这里没有理由使用
StreamWriter
——我建议直接处理
Stream
Encoding
API。
StreamWriter
的一个优点是,它可以在内部为
字节[]
重新使用缓冲区,但这是“优点”如果您在处理它之前只使用它进行一次
Write
,那么它是没有意义的,并且可以通过缓冲池轻松实现。

您没有调用
KeepAlive
-我们可以看看它是如何使用的吗?什么调用
SendMsg
?请注意,在同一个流上有两个单独的writer(或reader)是非常奇怪和错误的(我在
SendMsg
KeepAlive
中看到编剧)@marcGravel,我将在上面的问题中编辑它,但在AcceptConnections()中调用了KeepAlive).SendMsg是在main方法中调用的,我只是暂时将其注释掉。谢谢,我将尝试使用该构造函数。我想为keepalive ping重用流读取器和写入器,并使用一个单独的读取器和写入器来发送我自己的消息。您认为使用构造函数/仅使用1个读取器/写入器/还是使用流/编码API更好?@IanGlee儿子,你用你开心的东西。我会说:我一直在处理网络和IO代码(这正是我倾向于工作的领域):这里甚至没有一个可以想象的场景,我会在这里使用<代码> StreamReader < /C>或<代码> StreamWriter <代码>。谢谢你的帮助,我有很多事情要考虑。