1

我正在尝试替换以下可以正常工作的代码

TcpClient oC = new TcpClient(ip, port);
oC = new TcpClient(ip, port);
StreamReader messageReader;

try {
   messageReader = new StreamReader(oC.GetStream(), Encoding.ASCII);
   reply = messageReader.ReadLine();
}

try {
   using (messageReader = new StreamReader(oC.GetStream(), Encoding.ASCII))
   {
       reply = messageReader.ReadLine();
   }
}

但我得到一个InvalidOperationException说法

在未连接的套接字上不允许该操作。

有什么问题,我该如何解决?

更多:我在这段代码之前有 oc.Connect,所以我已连接,当它想第一次使用时工作正常,只有在那之后我才得到那个异常,我玩了一下它,现在我得到:

无法访问已释放的对象。\r\n对象名称: 'System.Net.Sockets.Socket'。

4

6 回答 6

12

在创建 StreamReader 之前尝试调用 oc.Connect。在连接套接字之前,没有任何内容可以实际读取,因此会出现异常。

于 2009-02-25T15:45:29.540 回答
4

只是重申我对 Jareds 答案的评论。

阿里评论:

在此之前我有 oc.Connect,它第一次工作正常,但第二次发生,我也得到“无法访问已处置的对象。\r\n对象名称:'System.Net.Sockets.Socket'。” – 阿里(13 分钟前)

我评论说:

“那是因为 StreamReader 获得了流的所有权,并关闭并处置了您启动它的 Stream。在这种情况下,是 TcpClient 的 NetworkStream。这里不需要处置 StreamReader”

于 2009-02-25T18:58:52.307 回答
2

所以使用正确的构造函数

using (messageReader = 
        new StreamReader(oC.GetStream(), Encoding.ASCII, false, 4096, true))
{
   reply = messageReader.ReadLine();
}

注意最后一个参数并阅读文档leaveOpen:中的含义。

但是,IIRC, StreamReader 缓冲流中的内容(默认情况下,读取 4096 字节),因此当您处理 StreamReader 时,您可能会惊讶地发现流的位置已经超出了您的数据末尾使用 StreamReader 读取。允许 StreamReader 取得所有权通常总是一个好主意。在读取所有数据之前,您不能让它保持打开状态吗?

于 2014-08-13T17:08:51.093 回答
1

听贾里德,你的实际异常,使用与它无关,你的尝试可以掩盖错误并隐藏真正的问题。真正的错误是您在尝试读取之前从未真正连接过您的套接字。

编辑:

听起来正在发生的是,您连接一次,然后连接被切断或对象失去作用域。在这种情况下,您需要做的可能是捕获断开连接并重新创建最初用于连接到服务器的套接字。一旦处理了该套接字,您就不能再次使用相同的引用,您必须实例化一个新的引用并使用它。

您是否有一个更完整的示例可以发布来显示您的连接范围与使用情况,以便我们可以准确地看到 GC 拾取底层套接字的位置?

于 2009-02-25T15:47:10.190 回答
1

此外,您将 messageReader 声明为 StreamWriter。它不应该是 StreamReader 吗?

StreamWriter messageReader;

[由 OP 修复]

另一个提示,最好在 using 语句中实例化一个对象,而不是将其传入。它可能不是您的异常的实际原因,而是来自 MSDN

您可以实例化资源对象,然后将变量传递给 using 语句,但这不是最佳实践。在这种情况下,对象在控制离开 using 块后仍保留在范围内,即使它可能不再有权访问其非托管资源。换句话说,它将不再被完全初始化。如果您尝试在 using 块之外使用该对象,则可能会引发异常。出于这个原因,通常最好在 using 语句中实例化对象并将其范围限制在 using 块中。

于 2009-02-25T15:48:15.167 回答
-3

我认为您不允许先定义 StreamWriter,然后将其与“使用”一起使用。

试试这个:

TcpClient oC = new TcpClient(ip, port);
oC = new TcpClient(ip, port);

try {
   using (StreamWriter messageReader = new StreamReader(oC.GetStream(), Encoding.ASCII))
   {
       reply = messageReader.ReadLine();
   }
}
于 2009-02-25T15:47:35.870 回答