How To Signal End Of Data Without Closing NetworkStream in C#

前端 未结 2 1282
广开言路
广开言路 2020-12-18 04:10

I have a client application that serializes a object and sends it to a server application. The server should deserialize the object, make changes to it, then serialize it an

相关标签:
2条回答
  • 2020-12-18 04:46

    You can signal "end of data" by closing only your half of the duplex TCP connection. This is accomplished with Socket.Disconnect.

    See how it works with this example, which I kept similar to yours. The client sends the data and then calls Disconnect; this allows ReadToEnd to return while still keeping the server's half of the connection open. The server then sends a response and also disconnects, after which both parties can Close their end of the connection to tear it down.

    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;
    }
    
    0 讨论(0)
  • 2020-12-18 04:52

    You could use a higher level framework like WCF, or if you are hell-bent on managing your own streams, then don't use ReadToEnd()- use ReadLine() (and have the client send messages as lines), or use Read() and have a special character (a sentinel) represent the end of a message.

    0 讨论(0)
提交回复
热议问题