0

i want to use the DataContractJsonSerializer class in combination with the TcpClient to receive and send JSON serialized objects. I am able to send JSON serialized objects but the receiving part does not work.

Source code of sending objects:

IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, tcpPort);
TcpClient tcpClient = new TcpClient();
tcpClient.Connect(endPoint);
var ser = new DataContractJsonSerializer(typeof(....));
 ser.WriteObject(tcpClient.GetStream(), req);

Source code of receiving objects:

var deser = new DataContractJsonSerializer(typeof(...));
var resp = (....)deser.ReadObject(tcpClient.GetStream());

The method ReadObject is hanging. Can anyone tell me the issue and how I can solve it? Thanks in advance.

Best regards

dbc
  • 104,963
  • 20
  • 228
  • 340
  • You may have a timing issue. The receiving code will only read what is in the buffer and not wait until all the data is received. So adding a network stream to the tclclient stream may be needed to wait. See : https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.networkstream?view=net-6.0 – jdweng Apr 17 '22 at 10:01
  • Thanks @jdweng How can i wrap the tcpclient into the network stream ? – user3452883 Apr 17 '22 at 12:55
  • Assuming you are flushing the stream on the client side, I believe that the reader returned by [`JsonReaderWriterFactory.CreateJsonReader()`](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.serialization.json.jsonreaderwriterfactory.createjsonreader) is trying to read beyond the last JSON token to confirm the entire stream is well-formed JSON (i.e. no garbage at end) and hangs doing that. – dbc Apr 17 '22 at 16:00
  • For similar issues see [XmlSerializer Won't Deserialize over NetworkStream](https://stackoverflow.com/q/28492295/3744182) or [protobuf-net fails deserializing my class](https://stackoverflow.com/a/8901333/3744182). – dbc Apr 17 '22 at 16:01
  • I cannot close the tcp client connection or call the shutdown method, because there should be multiple transmissions. How can I solve the problem? – user3452883 Apr 18 '22 at 10:31
  • Use [message framing](https://blog.stephencleary.com/2009/04/message-framing.html). When sending either serialize to a local MemoryStream then write the number of bytes into the NetworkStream as a prefix to each message, or use some sentinel character that never appears in well-formed UTF8 XML such as `'\0'` to mark the end of each message. Then when receiving, read only the specified number of bytes / only until the sentinel into a local MemoryStream, then deserialize from that. – dbc Apr 18 '22 at 13:29
  • See e.g. [How to create TCP message framing for the stream](https://stackoverflow.com/a/47382719) or [TcpClient.GetStream().DataAvailable returns false, but stream has more data](https://stackoverflow.com/a/9088533/3744182) or [TCP client\server - client doesn't always read](https://stackoverflow.com/a/12699292/3744182). In fact this could be a duplicate of those, agree? – dbc Apr 18 '22 at 13:29

0 Answers0