gpt4 book ai didi

c# - 使用 Newtonsoft.Json 从网络流中反序列化数据挂起

转载 作者:太空宇宙 更新时间:2023-11-03 12:55:16 25 4
gpt4 key购买 nike

使用 JsonSerializer 通过套接字接收的数据:

var stream = new NetworkStream(socket);
var serializer = new JsonSerializer();

using (var sr = new StreamReader(stream, new UTF8Encoding(), false))
using (var jsonTextReader = new JsonTextReader(sr))
{
var result = serializer.Deserialize(jsonTextReader).ToString();
}

但是当从套接字接收到的数据长度约为 2890 字节时,对 Deserialize 的调用挂起。

可以使用此代码轻松重现(当 jsonArrayElementsCount = 192 - 好的,当 193 - 它挂起):

using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Newtonsoft.Json;

namespace JsonNetHangsTest
{
class Program
{
static void Main(string[] args)
{
const int port = 11999;
const int jsonArrayElementsCount = 193;

var serverStartedEvent = new ManualResetEvent(false);
var clientReceivedEvent = new ManualResetEvent(false);

#region server
ThreadPool.QueueUserWorkItem(work =>
{
var server = new TcpListener(IPAddress.Parse("0.0.0.0"), port);
server.Start();

serverStartedEvent.Set();

var serverSocket = server.AcceptSocket();

var jsonString = "[\r\n" + String.Join(",", Enumerable.Repeat(" \"testdata\"\r\n", jsonArrayElementsCount)) + "]";
var bytes = new UTF8Encoding().GetBytes(jsonString);
serverSocket.Send(bytes);
Console.WriteLine("server send: " + bytes.Length);

clientReceivedEvent.WaitOne();

});
#endregion

serverStartedEvent.WaitOne();

var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect("127.0.0.1", port);

var stream = new NetworkStream(socket);
var serializer = new JsonSerializer();

using (var sr = new StreamReader(stream, new UTF8Encoding(), false))
using (var jsonTextReader = new JsonTextReader(sr))
{
var result = serializer.Deserialize(jsonTextReader).ToString();
Console.WriteLine("client receive: " + new UTF8Encoding().GetBytes(result).Length);
}

clientReceivedEvent.Set();
Console.ReadKey();
}
}
}

我在这里错过了什么?

最佳答案

您的问题是您发送的 JSON 的尾端正在服务器端进行缓冲。来自docs :

There is also no guarantee that the data you send will appear on the network immediately. To increase network efficiency, the underlying system may delay transmission until a significant amount of outgoing data is collected. A successful completion of the Send method means that the underlying system has had room to buffer your data for a network send.

因此您需要确保套接字缓冲区被刷新。但是,Socket 上没有 Flush() 方法。 .那么,该怎么办?

  1. 最简单的做法是在处理完套接字后立即处理它:

            int byteCount;
    using (var serverSocket = server.AcceptSocket())
    {
    byteCount = serverSocket.Send(bytes);
    }
    Console.WriteLine("server send: " + byteCount);

    (用完一次性用品后立即处理是个好主意。)

  2. 或者,将 serverSocket 包装在拥有套接字的 NetworkStream 中,然后释放流(这相当于同一件事):

            var serverSocket = server.AcceptSocket();
    using (var ns = new NetworkStream(serverSocket, true))
    {
    ns.Write(bytes, 0, bytes.Length);
    }

    (但请参阅 NetworkStream.Write vs. Socket.Send,这表明有时有必要检查从 serverSocket.Send(bytes) 返回的值。)

您可能需要考虑处理 SocketError.NoBufferSpaceAvailable .这里有一个如何做到这一点的建议:C# Examples: Socket Send and Receive [C#] .

关于c# - 使用 Newtonsoft.Json 从网络流中反序列化数据挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34130323/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com