如何在不关闭C#中的NetworkStream的情况下发出数据结束信号

我有一个客户端应用程序,它序列化一个对象并将其发送到服务器应用程序。 服务器应反序列化对象,对其进行更改,然后对其进行序列化并将其发回。

服务器代码:

TcpClient client = server.AcceptTcpClient(); using(NetworkStream stream = client.GetStream()) { using(StreamReader streamReader = new StreamReader(stream)) { string xmlData = streamReader.ReadToEnd(); } } 

除非客户端关闭流,否则ReadToEnd不会返回。 但是如果客户端关闭了流,我就无法发送响应。

有一个更好的方法吗?

您可以通过仅关闭双工TCP连接的一半来发出“数据结束”的信号 。 这是通过Socket.Disconnect实现的。

看看这个例子是如何工作的,我和你的例子保持一致。 客户端发送数据然后调用Disconnect ; 这允许ReadToEnd返回, 同时仍然保持服务器的一半连接打开 。 然后,服务器发送响应并断开连接,之后双方都可以Close它们的连接结束以将其拆除。

 static void Main(string[] args) { Action clientCode = () => { var buffer = new byte[100]; var clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); clientSocket.Connect(IPAddress.Loopback, 6690); clientSocket.Send(buffer); clientSocket.Disconnect(false); Console.WriteLine("Client: message sent and socket disconnected."); while (true) { var bytesRead = clientSocket.Receive(buffer); if (bytesRead == 0) { break; } Console.WriteLine("Client: read " + bytesRead + " bytes."); } clientSocket.Dispose(); }; var server = new TcpListener(IPAddress.Loopback, 6690); var thread = new Thread(new ThreadStart(clientCode)); server.Start(); thread.Start(); var client = server.AcceptTcpClient(); using(NetworkStream stream = client.GetStream()) { using(StreamReader streamReader = new StreamReader(stream)) { var data = streamReader.ReadToEnd(); Console.WriteLine("Server: read " + data.Length + " bytes."); // Since we 're here we know that the client has disconnected. // Send the response before StreamReader is disposed, because // that will cause the socket itself to be closed as well! Thread.Sleep(TimeSpan.FromSeconds(1)); Console.WriteLine("Server: sending response."); stream.Write(new byte[10], 0, 10); Console.WriteLine("Server: closing socket."); } } server.Stop(); Console.WriteLine("Server: waiting for client thread to complete."); thread.Join(); return; } 

您可以使用更高级别的框架,如WCF,或者如果您一心想管理自己的流,那么不要使用ReadToEnd() – 使用ReadLine()(并让客户端将消息作为行发送),或者使用Read ()并有一个特殊字符(一个哨兵 )代表一个消息的结尾。