使用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();
}
}
}
我在这里缺少什么?
答案 0 :(得分:1)
您的问题是您发送的JSON的尾端正在服务器端缓冲。来自docs:
也无法保证您发送的数据会立即显示在网络上。为了提高网络效率,底层系统可能会延迟传输,直到收集到大量的传出数据。成功完成Send方法意味着底层系统有足够的空间来缓冲网络发送的数据。
因此,您需要确保刷新套接字缓冲区。但是,Socket
上没有Flush()
方法。那么,该怎么办?
最简单的方法是在完成后立即处理套接字:
int byteCount;
using (var serverSocket = server.AcceptSocket())
{
byteCount = serverSocket.Send(bytes);
}
Console.WriteLine("server send: " + byteCount);
(一旦完成一次性用品的处理,总是一个好主意。)
或者,将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#]。