繁体   English   中英

为什么InputStreamReader无法读取websocket包的内容?

[英]Why InputStreamReader cannot read the content of a websocket package?

为了了解websocket的行为,我在Java中创建了一个简单的SocketServer来交换消息。 服务器应遵循以下操作:

1)在8080端口监听

2)在浏览器客户端上手动生成并由服务器接收的Websocket握手消息。

3)构建对握手消息的响应并回复客户端

4)实际读取具有相同连接的websocket信息字节。

该问题已在步骤4发生。当服务器以握手消息响应时,InputStreamReader不再能够接收任何新消息。 即使客户端已经发送了消息,它也会在readline()方法上阻止。 从wireshark中,我可以看到客户端发送了消息并且服务器响应了ack。 任何帮助,将不胜感激,谢谢。

更新:我刚刚注意到这个问题已经问过了。 我将首先研究其他帖子上的建议。

更新:行为与此博文相同: 奇怪的网络套接字行为:仅在关闭选项卡发送数据当网络选项卡关闭时,读取流接收到数据包。

Wireshark屏幕截图:

tcp流跟踪

包裹顺序

日志:

inputline: GET / HTTP/1.1
inputline: Host: localhost:8080
inputline: Connection: Upgrade
inputline: Pragma: no-cache
inputline: Cache-Control: no-cache
inputline: Upgrade: websocket
inputline: Origin: file://
inputline: Sec-WebSocket-Version: 13
inputline: User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36
inputline: Accept-Encoding: gzip, deflate, br
inputline: Accept-Language: en,zh-TW;q=0.8,zh;q=0.6,zh-CN;q=0.4
inputline: Sec-WebSocket-Key: Yin4xn04vr9iBH1b2dU15A==
inputline: Sec-WebSocket-Extensions: permessage-deflate;    client_max_window_bits
inputline: 
response: HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: +Y9whLTzCdyN1INpAxjkO6yD2Nw=

服务器套接字代码:

public class EchoServer {
public static String HTTP_VERSION_HEADER = "HTTP/1.1";
public static void main(String[] args) throws IOException {

    int portNumber = 8080;

    try (
        ServerSocket serverSocket =
            new ServerSocket(Integer.parseInt("8080"));
        Socket clientSocket = serverSocket.accept();     
        PrintWriter out =
            new PrintWriter(clientSocket.getOutputStream(), true);                   
        BufferedReader in = new BufferedReader(
            new InputStreamReader(clientSocket.getInputStream()));
    ) {
        String inputLine;
        StringBuilder sb = new StringBuilder();
        while ( true) {
                inputLine = in.readLine();
                if(inputLine == null) {
                    System.out.println("input is null");
                    continue;
                }
                System.out.println("inputline: " + inputLine);
                sb.append(inputLine).append(System.lineSeparator());
                if(inputLine.equals("")) {
                        Message msg = new Message(sb.toString(), new Date());
                        HttpMessage tmpMessage = new HttpMessage(msg.getText(), new Date());
                        String response = generateHandshakeResponse(tmpMessage);
                        System.out.println("response: " + response);
                        out.println(response);
                        out.flush();
                }
        }
    } catch (IOException e) {
        System.out.println("Exception caught when trying to listen on port "
            + portNumber + " or listening for a connection");
        System.out.println(e.getMessage());
    }
}

private static String generateHandshakeResponse(HttpMessage message) {
    String webSocketKey = message.getVal(HttpMessage.SEC_WEBSOCKET_KEY);
    String webSocketAccept = webSocketKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
    byte[] bytes = DigestUtils.sha1(webSocketAccept);
    String secWebSocketAcceptVal = Base64.encodeBase64String(bytes);

    StringBuilder sb = new StringBuilder();
    sb.append(HTTP_VERSION_HEADER).append(" 101 ").append("Switching Protocols\r\n");
    sb.append("Upgrade: websocket\r\n");
    sb.append("Connection: Upgrade\r\n");
    sb.append("Sec-WebSocket-Accept: ").append(secWebSocketAcceptVal).append("\r\n");
    sb.append("\n\n") //<--- this line fixed the problem
    //log.debug(sb.toString());
    return sb.toString();
    }
}

客户端代码:

<!doctype html>
<html lang="en">
<head>
<title>Websocket Client</title>
</head>
<body>
<script>
var exampleSocket = new WebSocket("ws://localhost:8080");
exampleSocket.onopen = function (event) {
  console.log("connection opened..");
  exampleSocket.send("Can you hear me?"); 
};
exampleSocket.onmessage = function (event) {
  console.log(event.data);
}

function sendMsg(){
  console.log("send message..");
  exampleSocket.send("hello hello");
}
</script>
<button onclick="sendMsg()" title="send">send</button>
</body>
</html>

非常感谢EJP,问题在于响应握手中缺少空白行以指示消息的结尾。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM