#javascript #.net #websocket
#javascript #.net #websocket
Вопрос:
Я создаю сервер .net websocket на основе TcpClient и NetworkStream, взаимодействующих с клиентом Javascript. После рукопожатия клиент запрашивает сервер для выполнения определенных действий, и сервер генерирует ответ — до сих пор это были короткие строки JSON, отправляемые обратно клиенту — и все работает нормально.
После того, как я получил требование отправлять более крупные строковые ответы (а именно, изображения в кодировке base64 с 200k и более байтами), клиент перестал получать ответы, и событие onmessage не запускается. Если я переключусь и отправлю короткий json — он снова работает нормально.
Когда я отправляю большие данные:
Когда я отправляю простые данные:
На стороне клиента я удалил код из всего, что не связано (поведение осталось прежним)
try{
ws = new WebSocket("ws://127.0.0.1:8282");
ws.binaryType = "arraybuffer";
}
catch(err){
debugger;
document.getElementById("message").innerHTML = "Not Connected! " err;
};
ws.onopen = function () {
var jsonRequest = '{"action" : "START_STREAM","timeout" : 20}';
ws.send("START_STREAM");
};
На стороне сервера я изолировал код после генерации ответа (обычная строка с изображением в кодировке base64, которое я протестировал и правильно декодировал):
Byte[] frame = CreateFrameFromString(serverResponse);
networkStream.Write(frame, 0, frame.Count());
networkStream.Flush();
clientSocket.Close();
clientSocket = ServerListener.AcceptTcpClient();
networkStream = clientSocket.GetStream();
Код для инициализации серверного потока:
ServerListener.Start();
clientSocket = ServerListener.AcceptTcpClient();
NetworkStream networkStream = clientSocket.GetStream();
while (true)
{
if (!networkStream.DataAvailable)
...regular loop/server stuff/handshake etc.
Ниже приведен метод CreateFrameFromString. Код операции проверяется со значениями 0-10, и во всех случаях поведение было одинаковым — ответ не был получен на стороне клиента.
private static byte[] CreateFrameFromString(string message, Opcode opcode = Opcode.Text)
{
var payload = Encoding.UTF8.GetBytes(message);
byte[] frame;
if (payload.Length < 126)
{
frame = new byte[1 /*op code*/ 1 /*payload length*/ payload.Length /*payload bytes*/];
frame[1] = (byte)payload.Length;
Array.Copy(payload, 0, frame, 2, payload.Length);
}
else if (payload.Length >= 126 amp;amp; payload.Length <= 65535)
{
frame = new byte[1 /*op code*/ 1 /*payload length option*/ 2 /*payload length*/ payload.Length /*payload bytes*/];
frame[1] = 126;
frame[2] = (byte)((payload.Length >> 8) amp; 255);
frame[3] = (byte)(payload.Length amp; 255);
Array.Copy(payload, 0, frame, 4, payload.Length);
}
else
{
frame = new byte[1 /*op code*/ 1 /*payload length option*/ 8 /*payload length*/ payload.Length /*payload bytes*/];
frame[1] = 127; // <-- Indicates that payload length is in following 8 bytes.
frame[2] = (byte)((payload.Length >> 56) amp; 255);
frame[3] = (byte)((payload.Length >> 48) amp; 255);
frame[4] = (byte)((payload.Length >> 40) amp; 255);
frame[5] = (byte)((payload.Length >> 32) amp; 255);
frame[6] = (byte)((payload.Length >> 24) amp; 255);
frame[7] = (byte)((payload.Length >> 16) amp; 255);
frame[8] = (byte)((payload.Length >> 8) amp; 255);
frame[9] = (byte)(payload.Length amp; 255);
Array.Copy(payload, 0, frame, 10, payload.Length);
}
frame[0] = (byte)((byte)opcode | 0x80 /*FIN bit*/);
return frame;
}
Я что-то упускаю — протокол / размер буфера / и т.д.? Во время тестирования я заметил, что могу отправить ответ до 4250 символов с вышеуказанной настройкой без каких-либо изменений. Как только я набрал это число, ответ начал исчезать.
Ответ №1:
После долгих поисков и устранения неполадок оказалось, что мне пришлось отправлять данные в пакетах, а не целиком. Я разделил ответ на куски (50000 символов) и отправил их 1 на 1, в то время как на стороне клиента я собирал фрагменты в событии onmessage. После того, как все фрагменты ответа были отправлены, я закрыл сеанс, который на стороне клиента вызвал создание образа из потока base64.