socket inputstream读取不到websocket 数据包,请大家帮忙看看。
Closed this issue · 2 comments
尝试用java socket实现简单的websocket信息交换,我的理解是分成以下的简单几步:
1)建立ServerSocket,并且监听 8080 (自己制定的端口)
2)用javascript建立Websocket,并发送 handshake 信息。
3)ServerSocket 收到 握手请求,发送回复
4)Websocket收到握手回复,验证sec-websocket-accept header,如果正确,发送消息数据包
5)ServerSocket 收到数据包,进行websocket数据包格式验证,读取payload.
我的问题是出在第5步, 验证的sec-websocket-accept显示正确,但回复的数据包在inputstream上面读不出来。 感觉就是readline()命令完全没有收到任何byte,哪怕是encoded的数据, 一直wait在数据流上面。 从wireshark上来看,client端已经发送了数据,server也返回了ack回复, 说明收到了,可是stream就是没有消息。。
以下是全部log, readline在发了握手回复之后再也没有收到inputstream的消息。
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: keY/5XS7qWTLVop5h88axw==
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: /f4sn4/rmtjrgIUTRUhJPkS6KoQ=
这里是chrome的截图,显示收到了握手回复
这里是wireshark的tcp stream 截图和package sequence的截图
以下是我的test server 代码。
`
package com.early.main;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import com.early.socket.message.HttpMessage;
import com.early.socket.message.Message;
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"); //<--- 这行修复了问题
//log.debug(sb.toString());
return sb.toString();
}
}
`
以下是我javascript websocket 的代码 (github的code格式怎么也没有调整好, 请大家凑合看一下):
<!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>
类似的情况在stackoverflow上也有一个帖子。https://stackoverflow.com/q/10742247/7466185
在网页关闭的时候, inputstream可以读出来数据了。 这个好奇怪。 感觉就像是websocket 没有flush一样。 有没有谁对前端websocket比较熟的可以给出一些建议
问题找到了。。少打了一个空行去标识信息结束。。