WebSocket 无法发送大数据
Posted
技术标签:
【中文标题】WebSocket 无法发送大数据【英文标题】:WebSocket is not able to send large data 【发布时间】:2012-12-31 14:38:39 【问题描述】:如何在 Java Script 中向 WebSocket 发送大数据?
使用下面的代码,我可以发送 126 个字符的数据,但不能超过这个。 (用 C# 编写)
public static void SendData(string text)
foreach (SocketClient client in ClientList)
if (client.Client.Connected)
try
NetworkStream l_Stream = client.Client.GetStream();
List<byte> lb = new List<byte>();
lb = new List<byte>();
lb.Add(0x81);
int size = text.Length;
lb.Add((byte)size);
lb.AddRange(Encoding.UTF8.GetBytes(text));
l_Stream.Write(lb.ToArray(), 0, size + 2);
catch
CloseClient(client);
有人可以帮帮我吗?我尝试了很多东西,但没有一个对我有用。
我正在使用 Chrome 25。
【问题讨论】:
这段代码有什么问题? 它不会发送超过 126 个字符的数据。 【参考方案1】:这是根据 RFC 6455 的 websocket 框架的外观:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
您在字节 1 中设置 websocket 帧的有效负载长度(第二个字节 - 第一个字节是字节 0)。一个字节只能有 256 个状态。但是字节 1 的第一位用于屏蔽标志。所以你只能表示 0 到 127 之间的值。
当有效载荷长度大于 125 时,您必须将字节 1 设置为 126,并将长度放入字节 2 和 3(“扩展有效载荷长度”)。当您的有效负载甚至超过 65535 字节时,您必须将字节 1 设置为 127 并将有效负载长度放入字节 2-9(“扩展有效负载长度”和“扩展有效负载长度”)。当您的有效载荷长度甚至大于 64 位(16 艾字节,或约 1600 万兆兆字节)时,那么......您应该发送一堆装满硬盘的卡车。
更多详情请见in the official Websocket RFC。
【讨论】:
爱你评论,尤其是“..你应该派一堆装满硬盘的卡车。”很好的答案!【参考方案2】:您可以向 WebSocket 发送任意大小的数据,但大数据会被分片。
检查这个:https://datatracker.ietf.org/doc/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5 和 5.4
和
pastebin.com/TxGZaHTY
和
http://buildnewgames.com/websockets/
了解更多信息。
【讨论】:
Websocket 碎片自动发生在发送方一侧。当您不想时,您不必将消息分割成多个 WS 帧。额外的碎片可能发生在 TCP/IP 层,但这通常由底层网络堆栈处理。 感谢您的澄清。【参考方案3】:来自this blog。在 WebSocket 服务器中发送和接收的单个有效负载大小可能存在限制。比如在tomcat中,默认是8192字节,checkout org.apache.tomcat.websocket.textBufferSize
in tomcat's doc.
因此,请确保您的 WebSocket 服务器中是否有任何有效负载大小限制,如果是,则将其作为部分有效负载接收。
【讨论】:
【参考方案4】:package GoodExample;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import sun.misc.BASE64Encoder;
/**
*
* @author
* Anders, Improved by Christopher Price
*/
public class WebRTCSignal
public static final int MASK_SIZE = 4;
public static final int SINGLE_FRAME_UNMASKED = 0x81;
private ServerSocket serverSocket;
private Socket socket;
public WebRTCSignal() throws IOException
serverSocket = new ServerSocket(1337);
connect();
private void connect() throws IOException
System.out.println("Listening");
socket = serverSocket.accept();
System.out.println("Got connection");
if(handshake())
listenerThread();
private boolean handshake() throws IOException
PrintWriter out = new PrintWriter(socket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
HashMap<String, String> keys = new HashMap<>();
String str;
//Reading client handshake
while (!(str = in.readLine()).equals(""))
String[] s = str.split(": ");
System.out.println();
System.out.println(str);
if (s.length == 2)
keys.put(s[0], s[1]);
//Do what you want with the keys here, we will just use "Sec-WebSocket-Key"
String hash;
try
hash = new BASE64Encoder().encode(MessageDigest.getInstance("SHA- 1").digest((keys.get("Sec-WebSocket-Key") + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes()));
catch (NoSuchAlgorithmException ex)
ex.printStackTrace();
return false;
//Write handshake response
out.write("HTTP/1.1 101 Switching Protocols\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Accept: " + hash + "\r\n"
+ "Origin: http://face2fame.com\r\n"
+ "\r\n");
out.flush();
return true;
private byte[] readBytes(int numOfBytes) throws IOException
byte[] b = new byte[numOfBytes];
socket.getInputStream().read(b);
return b;
public void sendMessage(byte[] msg) throws IOException
System.out.println("Sending to client");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedOutputStream os = new BufferedOutputStream(socket.getOutputStream());
baos.write(SINGLE_FRAME_UNMASKED);
baos.write(msg.length);
baos.write(msg);
baos.flush();
baos.close();
convertAndPrint(baos.toByteArray());
os.write(baos.toByteArray(), 0, baos.size());
os.flush();
public void listenerThread()
Thread t = new Thread(new Runnable()
@Override
public void run()
try
while (true)
System.out.println("Recieved from client: " + reiceveMessage());
System.out.println("Enter data to send");
catch (IOException ex)
ex.printStackTrace();
);
t.start();
public String reiceveMessage() throws IOException
byte[] buf = readBytes(2);
//dont use this byte[] buf2 = readBytes(4);
int extendedsize = 0;
System.out.println("Headers:");
if(!convertAndPrintHeader(buf)) // This means we detected an extended message
String CaryOverDetectiona = new String("");
byte[] bufadder1 = buf.clone();
byte[] bufadder2 = readBytes(2);
byte[] array1and2 = new byte[bufadder1.length + bufadder2.length];
System.arraycopy(bufadder1, 0, array1and2, 0, bufadder1.length);
System.arraycopy(bufadder2, 0, array1and2, bufadder1.length, bufadder2.length);
for (byte b : array1and2)
CaryOverDetectiona = (String.format("%02X ", b));
System.out.print(CaryOverDetectiona);
int i = ((array1and2[1] & 0xFF) - 0x80);
//int c = ((array1and2[2] & 0xFF) - 0x80);
//System.out.println(c+128);
int j = ((array1and2[3] & 0xFF) - 0x80)+2;
//System.out.println("The size of this uber message is" + j);
extendedsize = i+j;
System.out.println("Extended Size is" + extendedsize);
//System.exit(0);
//convertAndPrint(buf2);// Check out the byte sizes
int opcode = buf[0] & 0x0F;
if (opcode == 8)
//Client want to close connection!
System.out.println("Client closed!");
socket.close();
System.exit(0);
return null;
else
int payloadSize = getSizeOfPayload(buf[1]);
if (extendedsize>=126)
payloadSize = extendedsize;
System.out.println("Payloadsize: " + payloadSize);
buf = readBytes(MASK_SIZE + payloadSize);
System.out.println("Payload:");
convertAndPrint(buf);
buf = unMask(Arrays.copyOfRange(buf, 0, 4), Arrays.copyOfRange(buf, 4, buf.length));
String message = new String(buf);
return message;
private int getSizeOfPayload(byte b)
//Must subtract 0x80 from masked frames
int a = b & 0xff;
//System.out.println("PAYLOAD SIZE INT" + a);
return ((b & 0xFF) - 0x80);
private byte[] unMask(byte[] mask, byte[] data)
for (int i = 0; i < data.length; i++)
data[i] = (byte) (data[i] ^ mask[i % mask.length]);
return data;
private boolean convertAndPrintHeader(byte[] bytes)
StringBuilder sb = new StringBuilder();
String CaryOverDetection = new String();
// We must test byte 2 specifically for this. In the next step we add length bytes perhaps?
//for(int i = 0; i < bytes.length; i++)
//
for (byte b : bytes)
CaryOverDetection = (String.format("%02X ", b));
if (CaryOverDetection.contains("FE"))
return false;
sb.append(String.format("%02X ", b));
System.out.println(sb.toString());
return true;
private void convertAndPrint(byte[] bytes)
StringBuilder sb = new StringBuilder();
for (byte b : bytes)
sb.append(String.format("%02X ", b));
System.out.println(sb.toString());
public static void main(String[] args) throws IOException, InterruptedException, NoSuchAlgorithmException
WebRTCSignal j = new WebRTCSignal();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (true)
System.out.println("Write something to the client!");
j.sendMessage(br.readLine().getBytes());
【讨论】:
欢迎来到 Stack Overflow。我不明白这是如何回答这个问题的 - 你能说得更清楚一点吗?以上是关于WebSocket 无法发送大数据的主要内容,如果未能解决你的问题,请参考以下文章