1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
| public class WebSocket {
private final ServerSocket serverSocket = new ServerSocket(8081);
@PreDestroy public void destroy() throws IOException { serverSocket.close(); }
public static void main(String[] args) throws IOException { WebSocket webSocket = new WebSocket(); }
public WebSocket() throws IOException { while (true) { Socket socket = serverSocket.accept(); OutputStream outputStream = socket.getOutputStream(); InputStream inputStream = socket.getInputStream(); Inflater inflater = new Inflater(true); Deflater deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true); new Thread(() -> {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
new Thread(() -> { try { byte[] bytes = new byte[1024]; int read; while (-1 != (read = inputStream.read(bytes))) { byteArrayOutputStream.write(bytes, 0, read); } } catch (IOException e) { throw new RuntimeException(e); } }).start();
try { boolean first = true; while (true) { ThreadUtil.sleep(10); if (byteArrayOutputStream.size() < 1) { continue; } byte[] bytes = byteArrayOutputStream.toByteArray(); byteArrayOutputStream.reset(); if (first) { String request = new String(bytes); System.out.println(request); Map<String, String> headers = getHeaders(request); String secWebsocketKey = headers.get("Sec-WebSocket-Key"); String secWebsocketAccept = calculateWebSocketAccept(secWebsocketKey); String response = "HTTP/1.1 101 \r\n" + "Connection: upgrade\r\n" + "Upgrade: websocket\r\n" + "Sec-WebSocket-Accept: " + secWebsocketAccept + "\r\n" + "Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15\r\n" + "\r\n"; IoUtil.write(outputStream, CharsetUtil.UTF_8, false, response); first = false; } else { if (isMask(bytes)) { int payloadLength = getPayloadLength(bytes); byte[] unMaskPayload = getUnMaskPayload(bytes, payloadLength); System.out.println(new String(decompressData(inflater, unMaskPayload, 0, payloadLength))); } String message = "hello"; byte[] compressData = compressData(deflater, message.getBytes()); byte[] data = createData(compressData.length, compressData); IoUtil.write(outputStream, false, data); } } } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } }).start(); } }
public static String calculateWebSocketAccept(String webSocketKey) throws NoSuchAlgorithmException { String magicString = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; String concatenated = webSocketKey + magicString; MessageDigest digest = MessageDigest.getInstance("SHA-1"); byte[] hashedBytes = digest.digest(concatenated.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(hashedBytes); }
public static Map<String, String> getHeaders(String request) { Map<String, String> map = new HashMap<>(); String[] lines = request.split("\r\n"); for (int i = 1; i < lines.length; i++) { String line = lines[i]; if (StringUtils.isBlank(line)) { break; } String[] split = line.split(": "); map.put(split[0], split[1]); } return map; }
public static byte[] decompressData(Inflater inflater, byte[] input, int offset, int position) { inflater.setInput(input, offset, position);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024];
try { while (!inflater.needsInput()){ int count = inflater.inflate(buffer); outputStream.write(buffer, 0, count); } inflater.setInput(new byte[]{0, 0, -1, -1}); inflater.inflate(buffer); } catch (DataFormatException e) { e.printStackTrace(); }
return outputStream.toByteArray(); }
public boolean isMask(byte[] bytes) { return (bytes[1] & 128) == 128; }
public int getPayloadLength(byte[] bytes) { int b = bytes[1] & 127; if (b == 126) { int result = 0; for (int i = 2; i < 4; i++) { result += (bytes[i] & 255) << (8 * (3 - i)); } return result; } else if (b == 127) { int result = 0; for (int i = 2; i < 10; i++) { result += (bytes[i] & 255) << (8 * (9 - i)); } return result; } else { return b; } }
public byte[] getUnMaskPayload(byte[] bytes, int payloadLength) { int position = payloadLength > 65535 ? 10 : payloadLength > 125 ? 4 : 2; byte[] maskingKeyBytes = ArrayUtil.sub(bytes, position, position + 4); byte[] maskPayloadBytes = ArrayUtil.sub(bytes, position + 4, position + 4 + payloadLength);
byte[] payload = new byte[payloadLength];
for (int i = 0; i < payloadLength; i++) { payload[i] = (byte) (maskPayloadBytes[i] ^ maskingKeyBytes[i % 4]); }
return payload; }
public static byte[] compressData(Deflater deflater, byte[] input) { byte[] bytes = new byte[1024];
deflater.setInput(input); int deflate = deflater.deflate(bytes, 0, bytes.length, Deflater.SYNC_FLUSH);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byteArrayOutputStream.write(bytes, 0, deflate - 4);
return byteArrayOutputStream.toByteArray(); }
public static byte[] createData(int payloadLength, byte[] maskData) { byte[] one = new byte[]{(byte) 193}; byte[] two; if (payloadLength > 65535) { two = new byte[8]; two[0] = 127; for (int i = 1; i < 9; i++) { two[i] = (byte) (payloadLength & (8 * (9 - i)) >> (8 * (8 - i))); } } else if (payloadLength > 125) { two = new byte[3]; two[0] = 126; two[1] = (byte) (payloadLength >> 8); two[2] = (byte) (payloadLength & 255); } else { two = new byte[]{(byte) payloadLength}; } return ArrayUtil.addAll(one, two, maskData); } }
|