我通过websocket接收JSON。至少:我是部分的。使用在线websocket服务,我收到完整的JSON响应(忽略所有HTML标记)。当我查看在控制台中收到的JSON时,我可以看到HTML标记(在调试过程中使用HTML查看器查看它会删除HTML)但它会突然结束(不完整的数据)。
我的缓冲区有足够的空间,我正在使用async-await(假设)在继续之前等待整个响应进来。
private async Task Receive()
{
var buffer = new byte[4096 * 20];
while (_socket.State == WebSocketState.Open)
{
var response = await _socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
if (response.MessageType == WebSocketMessageType.Close)
{
await
_socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Close response received",
CancellationToken.None);
}
else
{
var result = Encoding.UTF8.GetString(buffer);
var a = buffer[1000];
var b = buffer[10000];
var c = buffer[50000];
var d = buffer[81000];
Console.WriteLine(result);
var responseObject = JsonConvert.DeserializeObject<Response>(result, _requestParameters.ResponseDataType);
OnSocketReceive.Invoke(this, new SocketEventArgs {Response = responseObject });
buffer = new byte[4096 * 20];
}
}
}
注意事项:缓冲区足够大,b
,c
和d
永远不会被填充。我还应该注意,这只发生在1-questions-newest-tag-java
请求中,155-questions-active
完全正常。
在进行一些挖掘之后,我发现response.CloseStatus
和response.CloseStatusDescription
始终为null
,response.Count
始终为1396
(在Word中复制粘贴结果确实显示总共有1396个字符)而response.EndOfMessage
是false
。
挖掘some source code我发现DefaultReceiveBufferSize
为16 * 1024
(足够大)而WebSocketGetDefaultKeepAliveInterval()
指的是an external implementation(但调试器显示{ {1}})。
由于调试器在联机服务收到响应的同一时刻停止,因此不会超时。
为什么我的方法在套接字尚未收到所有数据时继续执行?
答案 0 :(得分:26)
只是为了完成@Noseratio响应,代码将是这样的:
ArraySegment<Byte> buffer = new ArraySegment<byte>(new Byte[8192]);
WebSocketReceiveResult result= null;
using (var ms = new MemoryStream())
{
do
{
result = await socket.ReceiveAsync(buffer, CancellationToken.None);
ms.Write(buffer.Array, buffer.Offset, result.Count);
}
while (!result.EndOfMessage);
ms.Seek(0, SeekOrigin.Begin);
if (result.MessageType == WebSocketMessageType.Text)
{
using (var reader = new StreamReader(ms, Encoding.UTF8))
{
// do stuff
}
}
}
干杯。
答案 1 :(得分:14)
我可能错了,但我认为你不应该一次收到完整的WebSocket
消息。服务器可能正在以块的形式发送消息(这对应于使用SendAsync
调用endOfMessage: false
)。
因此,在循环中执行await _socket.ReceiveAsync()
并累积收到的块,直到WebSocketReceiveResult.EndOfMessage
为true
或发生错误。
在旁注中,您可能应该使用WebSocket.CreateClientBuffer
而不是new ArraySegment<byte>(buffer)
。
答案 2 :(得分:4)
根据Noseratio的回答,我已经实现了一个临时缓冲区,用于构建整个消息的数据。
var temporaryBuffer = new byte[BufferSize];
var buffer = new byte[BufferSize * 20];
int offset = 0;
WebSocketReceiveResult response;
while (true)
{
response = await _socket.ReceiveAsync(
new ArraySegment<byte>(temporaryBuffer),
CancellationToken.None);
temporaryBuffer.CopyTo(buffer, offset);
offset += response.Count;
temporaryBuffer = new byte[BufferSize];
if (response.EndOfMessage)
{
break;
}
}
完整实施here
答案 3 :(得分:1)
// Read the bytes from the web socket and accumulate all into a list.
var buffer = new ArraySegment<byte>(new byte[1024]);
WebSocketReceiveResult result = null;
var allBytes = new List<byte>();
do
{
result = await webSocket.ReceiveAsync(buffer, CancellationToken.None);
for (int i = 0; i < result.Count; i++)
{
allBytes.Add(buffer.Array[i]);
}
}
while (!result.EndOfMessage);
// Optional step to convert to a string (UTF-8 encoding).
var text = Encoding.UTF8.GetString(allBytes.ToArray(), 0, allBytes.Count);
答案 4 :(得分:0)
试试这个:
try
{
WebSocketReceiveResult result;
string receivedMessage = "";
var message = new ArraySegment<byte>(new byte[4096]);
do
{
result = await WebSocket.ReceiveAsync(message, DisconectToken);
if (result.MessageType != WebSocketMessageType.Text)
break;
var messageBytes = message.Skip(message.Offset).Take(result.Count).ToArray();
receivedMessage += Encoding.UTF8.GetString(messageBytes);
}
while (!result.EndOfMessage);
if (receivedMessage != "{}" && !string.IsNullOrEmpty(receivedMessage))
{
ResolveWebSocketResponse.Invoke(receivedMessage, Connection);
Console.WriteLine("Received: {0}", receivedMessage);
}
}
catch (Exception ex)
{
var mes = ex.Message;
}