TcpClient:如何关闭并重新连接?

时间:2016-09-09 00:14:29

标签: c# tcpclient

您好,感谢您的帮助。 这次我想问一下TcpClient。 我有一个服务器程序,我正在编写一个客户端程序。 此客户端使用TcpClient。首先是创建一个新客户端

clientSocket=new TcpClient(); 

(顺便说一下,这会导致异常吗?以防我把它放在try-catch中,但我不确定是否真的有必要) 无论如何,后来我进入一个循环,在这个循环内我连接到服务器

clientSocket.Connect("xx.xx.xx.xx",port);

然后我用

创建一个NetworkStream
clientStream=clientSocket.GetStream();

然后通过Read开始等待来自服务器的数据。我知道这是阻塞所以我也设置了ReadTimeOut(比如1秒)

无论如何,到目前为止一切顺利。 如果我没有从服务器收到任何东西,我会尝试向它发送一些东西。如果这种情况持续发生3次,我想要关闭连接并再次重新连接到服务器

(注意一个完全不同的问题是当服务器以某种方式关闭时,导致客户端中的其他类型的错误 - 或许我稍后会问这个问题)

那么,我该怎么办?

 if(clientSocket.Connected)
            {
                Console.WriteLine("Closing the socket");
                clientSocket.Close();
            }

我关闭了套接字。 循环结束,所以我再次开始尝试连接到服务器。

clientSocket.Connect("xx.xx.xx.xx",port);

然而,这会导致错误(实际上是未处理的异常)“无法访问已处置的对象”

所以我的问题是 如何关闭并重新连接到服务器?

再次感谢您的帮助

3 个答案:

答案 0 :(得分:3)

TcpClient实例只能用于连接一次。你可以简单地实例化一个新的TcpClient,而不是试图重新打开一个封闭的。{/ p>

答案 1 :(得分:3)

the other answer中所述,TcpClient对象只能连接一次。如果要重新连接到服务器,则必须创建新的TcpClient对象并再次呼叫Connect()

那就是说,你的问题中有许多明显的误解:

  1. 首先也是最重要的一点,如果您有任何意图尝试再次使用ReceiveTimeout对象,则不应使用TcpClient,例如将一些数据发送到服务器。一旦超时时间到期,底层套接字就不再可用了。

    如果你想在服务器没有向你发送数据时定期向服务器发送数据,你应该使用异步I / O(无论如何,尽管存在学习曲线,您仍应该这样做)并使用常规计时器对象来跟踪自从您从服务器接收数据以来的时间。
  2. TcpClient构造函数当然可以抛出异常。至少,任何尝试new引用类型对象都可能抛出OutOfMemoryException,而在TcpClient的情况下,它最终会尝试创建本机套接字句柄也可能失败。

    虽然所有I / O对象和方法都可以抛出异常,但您应该只捕获有优雅处理的异常。因此,在向代码中添加try / catch块之前,请确定在异常情况下您要执行的操作,以确保您的代码不会损坏任何数据并继续操作正确。通常不能优雅地处理OutOfMemoryException(并且在任何情况下保护new的所有用法都是不切实际的),但是你当然可以捕获SocketException,它可能被构造函数抛出。如果抛出该异常,您应该立即放弃创建和使用TcpClient的尝试,并向用户报告错误,以便他们可以尝试纠正阻止套接字创建的任何问题。
  3. 如果您的服务器需要向您发送数据,而您没有收到数据,则关闭连接并重试不太可能改善这种情况。这只会导致服务器上的额外负载,使其更有可能无法响应。同样反复发送相同的数据。您的请求一次,等待服务器响应的实际时间,如果您在所需的时间内没有得到响应,请向用户报告错误并让他们决定做什么next。

    请注意,在这种情况下,你可以使用ReceiveTimeout属性,因为如果你没有得到回复你将要做的就是及时放弃了联系,这很好。

答案 2 :(得分:1)

很简单:

client.Close();
client = new TcpClient();
client.Connect(host, port);