Javascript 未在 IOS 上调用 Websocket OnOpen
Javascript Websocket OnOpen not being called on IOS
我一直在使用 websockets 在 Java 脚本中的服务器(在 Java)和客户端上工作,并且一切正常,只是在 Android 中找到,但是当我测试它时iPhone,Java脚本页面在任何 websocket.send 方法上挂起。
在Android上,gameButton函数运行通过,在页面上输出"Send!",服务器收到消息。在 IOS 上,gameButton 函数输出类似 "Input: u" 的内容,但显然在 connection.send 上挂起,不输出 "Sent!",服务器也没有收到消息。 onopen 函数从未在 iPhone 上调用,但在 Android 上调用。有任何想法吗?如果您需要查看一些服务器代码,请告诉我..
抱歉代码太长了!
Java客户端脚本:
<!DOCTYPE html>
<html>
<head>
<title>Echo Test</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
</head>
<body onload="pageLoad()" style="background:black; color:cyan">
<div id="joinform">
<input type="text" id="username" value="Username..."></input>
<button id="joinbutton" onclick="joinSubmit()">Join!</button></div>
<div id="gamecontrols">
<button onclick="gameButton('u')" id="upbutton"> UP </button>
<button onclick="gameButton('d')" id="downbutton">DOWN</button></div>
<div id="leftDiv" style="float:left; width=10%; height=300px"><canvas id="leftCanvas" style="border:2px solid cyan"></canvas> </div>
<div id="rightDiv" style="float:left; width=10%; height=300px"><canvas id="rightCanvas" style="border:2px solid cyan"></canvas> </div>
<div id="statusdiv"> </div>
<div id="messages"></div>
</body>
<script type="text/javascript">
var connection = new WebSocket('ws://174.51.xxx.xx:9091');
var messages = document.getElementById("messages");
var username = document.getElementById("username");
var joinbutton = document.getElementById("joinbutton");
var game = document.getElementById("gamecontrols");
var joinform = document.getElementById("joinform");
var state = 0;
var leftCanvas = document.getElementById('leftCanvas')
var rightCanvas = document.getElementById('rightCanvas');
var statusdiv = document.getElementById('statusdiv')
var startx = 0
var starty = 0;
var distx = 0;
var disty = 0;
// When the connection is open, send some data to the server
connection.onopen = function(e) {
writeResponse('Open!');
connection.send('TEST');
}
// Log errors
connection.onerror = function(error) {
writeResponse('Error: ' + error);
}
connection.onclose = function(e) {
writeResponse("Disconnected: " + e.data);
}
// Log messages from the server
connection.onmessage = function(e) {
writeResponse('Server: ' + e.data);
}
function pageLoad() {
game.style.visibility = "hidden";
}
function writeResponse(text) {
messages.innerHTML += "<br/>" + text;
}
function joinSubmit() {
game.style.visibility = "visible";
//connection.send(username.value);
writeResponse("Username sent to server.");
joinform.remove();
leftCanvas.addEventListener('touchstart', function(e) {
var touchobj = e.changedTouches[0] // reference first touch point (ie: first finger)
startx = parseInt(touchobj.clientX) // get x position of touch point relative to left edge of browser
starty = parseInt(touchobj.clientY)
statusdiv.innerHTML = 'Status: touchstart<br> ClientX: ' + startx + 'px'
drawJoystick(startx, starty);
e.preventDefault()
}, false)
leftCanvas.addEventListener('touchmove', function(e) {
e.preventDefault()
var touchobj = e.changedTouches[0] // reference first touch point for this event
var distx = parseInt(touchobj.clientX) - startx
var disty = parseInt(touchobj.clientY) - starty
statusdiv.innerHTML = 'Status: touchmove<br> Horizontal distance traveled: ' + distx + 'px<br> Vertical distance traveled: ' + disty + 'px' +
'<br>Dist: ' + Math.sqrt((startx - (distx + startx)) * (startx - (distx + startx)) + (starty - (disty + starty)) * (starty - (disty +
starty)));
//connection.send("L=" + distx + "=" + disty);
connection.send("A=" + Math.floor(angleBetween2Lines(startx, starty, startx + distx, starty + disty) + 90) * -1);
connection.send("B=" + distx + "=" + disty);
}, false)
leftCanvas.addEventListener('touchend', function(e) {
var touchobj = e.changedTouches[0] // reference first touch point for this event
statusdiv.innerHTML = 'Status: touchend<br> Resting x coordinate: ' + touchobj.clientX + 'px'
e.preventDefault()
}, false)
}
function gameButton(ctrl) {
writeResponse("Control: " + ctrl);
connection.send(ctrl);
writeResponse("Sent!");
}
function find_angle(x1, y1, x2, y2) {
var AB = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
var BC = Math.sqrt(Math.pow(x2 - (x1 - 10), 2) + Math.pow(y2 - y1, 2));
var AC = Math.sqrt(Math.pow((x1 - 10) - x1, 2) + Math.pow(y1 - y1, 2));
return Math.acos((BC * BC + AB * AB - AC * AC) / (2 * BC * AB)) * (180 / Math.PI);
}
function angleBetween2Lines(x1, y1, x2, y2) {
var angle1 = Math.atan2(y1 - y1,
x1 - (x1 + 100));
var angle2 = Math.atan2(y1 - y2,
x1 - x2);
return angle1 - angle2 * (180 / Math.PI);
}
</script>
</html>
编辑:我测试了此页面 http://websocket.org/echo.html 中的确切代码,它似乎在 Android 和 iOS 上都能正常工作,所以我不确定是什么原因造成的我的 websocket 实现在 iOS 上中断...有什么想法会导致 connection.send() 函数冻结并将 javascript 方法的其余部分阻塞到 运行?
更新:我将我的服务器代码减少到尽可能短的形式,它仍然可以在 Android 上运行,但在我尝试过的任何 iPhone 上都不能运行。此外,上面的 javascript 代码没有在 iPhone 中调用 "connection.onopen" 函数,而是在 Android...
中调用它
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.xml.bind.DatatypeConverter;
public class DateServer {
static String[] headers = new String[10];
static String[] bodies = new String[10];
public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
ServerSocket listener = new ServerSocket(9091);
try {
while (true) {
Socket socket = listener.accept();
System.out.println("Accepted");
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg;
while ((msg = input.readLine()) != null) {
if (msg.length() == 0)
break;
parseHeaders(msg);
}
String httpResponse = returnHeader();
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(httpResponse + "\n");
out.flush();
System.out.println("Sent HTTP Response");
} finally {
}
}
}
finally {
listener.close();
}
}
public static void parseHeaders(String in) {
System.out.println(in);
String[] thisLine = in.split(": ");
if (thisLine[0].equals("Host")) {
bodies[0] = thisLine[1];
}
else if (thisLine[0].equals("Upgrade")) {
bodies[1] = thisLine[1];
}
else if (thisLine[0].equals("Connection")) {
bodies[2] = thisLine[1];
}
else if (thisLine[0].equals("Sec-WebSocket-Key")) {
bodies[3] = thisLine[1];
}
else if (thisLine[0].equals("Sec-WebSocket-Version")) {
bodies [4] = thisLine[1];
}
}
public static String returnHeader() throws NoSuchAlgorithmException, UnsupportedEncodingException {
String head = "HTTP/1.1 101 Web Socket Protocol Handshake\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ";
String key = bodies[3];
String encoded = WebSocketAccept(key);
String httpResponse = head.concat(encoded);
httpResponse.concat("\r\n\r\n"); // is concat not working??
return httpResponse;
}
private static String WebSocketAccept(String message) throws NoSuchAlgorithmException, UnsupportedEncodingException {
message = message.concat("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
MessageDigest digest = MessageDigest.getInstance("SHA-1");
byte[] hashedBytes = digest.digest(message.getBytes("UTF-8"));
return convertByteArrayToHexString(hashedBytes);
}
private static String convertByteArrayToHexString(byte[] arrayBytes) {
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < arrayBytes.length; i++) {
stringBuffer.append(Integer.toString((arrayBytes[i] & 0xff) + 0x100, 16).substring(1));
}
return convertHexToBase64(stringBuffer.toString());
}
private static String convertHexToBase64(String hex) {
byte[] hexToBytes = DatatypeConverter.parseHexBinary(hex);
String base64 = Base64.getEncoder().encodeToString(hexToBytes);
System.out.println(base64);
return base64;
}
}
这是服务器从 Android 和 iPhone:
收到的 headers
Android:
GET / HTTP/1.1
Host: 174.51.xxx.xx:9091
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: http://server.site88.net
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Linux; Android 5.0; SM-G900V Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.91 Mobile Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Sec-WebSocket-Key: IKTSyKHA8zclXsm2hFzm5Q==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
iPhone:
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: 174.51.xxx.xx:9091
Origin: http://server.site88.net
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: Sq0xOYhkomBmiyMbGwp/kQ==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 9_2_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13D15 Safari/601.1
我想通了。当我创建 headers 从服务器发送回浏览器时,我使用 "httpResponse.concat("\r\n\r\n")" 在 headers 的末尾添加换行符,这根本行不通。将其更改为 "httpResponse = httpResponse + "\r\n\r\n";"确实有效。
我一直在使用 websockets 在 Java 脚本中的服务器(在 Java)和客户端上工作,并且一切正常,只是在 Android 中找到,但是当我测试它时iPhone,Java脚本页面在任何 websocket.send 方法上挂起。
在Android上,gameButton函数运行通过,在页面上输出"Send!",服务器收到消息。在 IOS 上,gameButton 函数输出类似 "Input: u" 的内容,但显然在 connection.send 上挂起,不输出 "Sent!",服务器也没有收到消息。 onopen 函数从未在 iPhone 上调用,但在 Android 上调用。有任何想法吗?如果您需要查看一些服务器代码,请告诉我..
抱歉代码太长了!
Java客户端脚本:
<!DOCTYPE html>
<html>
<head>
<title>Echo Test</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
</head>
<body onload="pageLoad()" style="background:black; color:cyan">
<div id="joinform">
<input type="text" id="username" value="Username..."></input>
<button id="joinbutton" onclick="joinSubmit()">Join!</button></div>
<div id="gamecontrols">
<button onclick="gameButton('u')" id="upbutton"> UP </button>
<button onclick="gameButton('d')" id="downbutton">DOWN</button></div>
<div id="leftDiv" style="float:left; width=10%; height=300px"><canvas id="leftCanvas" style="border:2px solid cyan"></canvas> </div>
<div id="rightDiv" style="float:left; width=10%; height=300px"><canvas id="rightCanvas" style="border:2px solid cyan"></canvas> </div>
<div id="statusdiv"> </div>
<div id="messages"></div>
</body>
<script type="text/javascript">
var connection = new WebSocket('ws://174.51.xxx.xx:9091');
var messages = document.getElementById("messages");
var username = document.getElementById("username");
var joinbutton = document.getElementById("joinbutton");
var game = document.getElementById("gamecontrols");
var joinform = document.getElementById("joinform");
var state = 0;
var leftCanvas = document.getElementById('leftCanvas')
var rightCanvas = document.getElementById('rightCanvas');
var statusdiv = document.getElementById('statusdiv')
var startx = 0
var starty = 0;
var distx = 0;
var disty = 0;
// When the connection is open, send some data to the server
connection.onopen = function(e) {
writeResponse('Open!');
connection.send('TEST');
}
// Log errors
connection.onerror = function(error) {
writeResponse('Error: ' + error);
}
connection.onclose = function(e) {
writeResponse("Disconnected: " + e.data);
}
// Log messages from the server
connection.onmessage = function(e) {
writeResponse('Server: ' + e.data);
}
function pageLoad() {
game.style.visibility = "hidden";
}
function writeResponse(text) {
messages.innerHTML += "<br/>" + text;
}
function joinSubmit() {
game.style.visibility = "visible";
//connection.send(username.value);
writeResponse("Username sent to server.");
joinform.remove();
leftCanvas.addEventListener('touchstart', function(e) {
var touchobj = e.changedTouches[0] // reference first touch point (ie: first finger)
startx = parseInt(touchobj.clientX) // get x position of touch point relative to left edge of browser
starty = parseInt(touchobj.clientY)
statusdiv.innerHTML = 'Status: touchstart<br> ClientX: ' + startx + 'px'
drawJoystick(startx, starty);
e.preventDefault()
}, false)
leftCanvas.addEventListener('touchmove', function(e) {
e.preventDefault()
var touchobj = e.changedTouches[0] // reference first touch point for this event
var distx = parseInt(touchobj.clientX) - startx
var disty = parseInt(touchobj.clientY) - starty
statusdiv.innerHTML = 'Status: touchmove<br> Horizontal distance traveled: ' + distx + 'px<br> Vertical distance traveled: ' + disty + 'px' +
'<br>Dist: ' + Math.sqrt((startx - (distx + startx)) * (startx - (distx + startx)) + (starty - (disty + starty)) * (starty - (disty +
starty)));
//connection.send("L=" + distx + "=" + disty);
connection.send("A=" + Math.floor(angleBetween2Lines(startx, starty, startx + distx, starty + disty) + 90) * -1);
connection.send("B=" + distx + "=" + disty);
}, false)
leftCanvas.addEventListener('touchend', function(e) {
var touchobj = e.changedTouches[0] // reference first touch point for this event
statusdiv.innerHTML = 'Status: touchend<br> Resting x coordinate: ' + touchobj.clientX + 'px'
e.preventDefault()
}, false)
}
function gameButton(ctrl) {
writeResponse("Control: " + ctrl);
connection.send(ctrl);
writeResponse("Sent!");
}
function find_angle(x1, y1, x2, y2) {
var AB = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
var BC = Math.sqrt(Math.pow(x2 - (x1 - 10), 2) + Math.pow(y2 - y1, 2));
var AC = Math.sqrt(Math.pow((x1 - 10) - x1, 2) + Math.pow(y1 - y1, 2));
return Math.acos((BC * BC + AB * AB - AC * AC) / (2 * BC * AB)) * (180 / Math.PI);
}
function angleBetween2Lines(x1, y1, x2, y2) {
var angle1 = Math.atan2(y1 - y1,
x1 - (x1 + 100));
var angle2 = Math.atan2(y1 - y2,
x1 - x2);
return angle1 - angle2 * (180 / Math.PI);
}
</script>
</html>
编辑:我测试了此页面 http://websocket.org/echo.html 中的确切代码,它似乎在 Android 和 iOS 上都能正常工作,所以我不确定是什么原因造成的我的 websocket 实现在 iOS 上中断...有什么想法会导致 connection.send() 函数冻结并将 javascript 方法的其余部分阻塞到 运行?
更新:我将我的服务器代码减少到尽可能短的形式,它仍然可以在 Android 上运行,但在我尝试过的任何 iPhone 上都不能运行。此外,上面的 javascript 代码没有在 iPhone 中调用 "connection.onopen" 函数,而是在 Android...
中调用它import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.xml.bind.DatatypeConverter;
public class DateServer {
static String[] headers = new String[10];
static String[] bodies = new String[10];
public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
ServerSocket listener = new ServerSocket(9091);
try {
while (true) {
Socket socket = listener.accept();
System.out.println("Accepted");
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg;
while ((msg = input.readLine()) != null) {
if (msg.length() == 0)
break;
parseHeaders(msg);
}
String httpResponse = returnHeader();
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(httpResponse + "\n");
out.flush();
System.out.println("Sent HTTP Response");
} finally {
}
}
}
finally {
listener.close();
}
}
public static void parseHeaders(String in) {
System.out.println(in);
String[] thisLine = in.split(": ");
if (thisLine[0].equals("Host")) {
bodies[0] = thisLine[1];
}
else if (thisLine[0].equals("Upgrade")) {
bodies[1] = thisLine[1];
}
else if (thisLine[0].equals("Connection")) {
bodies[2] = thisLine[1];
}
else if (thisLine[0].equals("Sec-WebSocket-Key")) {
bodies[3] = thisLine[1];
}
else if (thisLine[0].equals("Sec-WebSocket-Version")) {
bodies [4] = thisLine[1];
}
}
public static String returnHeader() throws NoSuchAlgorithmException, UnsupportedEncodingException {
String head = "HTTP/1.1 101 Web Socket Protocol Handshake\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ";
String key = bodies[3];
String encoded = WebSocketAccept(key);
String httpResponse = head.concat(encoded);
httpResponse.concat("\r\n\r\n"); // is concat not working??
return httpResponse;
}
private static String WebSocketAccept(String message) throws NoSuchAlgorithmException, UnsupportedEncodingException {
message = message.concat("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
MessageDigest digest = MessageDigest.getInstance("SHA-1");
byte[] hashedBytes = digest.digest(message.getBytes("UTF-8"));
return convertByteArrayToHexString(hashedBytes);
}
private static String convertByteArrayToHexString(byte[] arrayBytes) {
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < arrayBytes.length; i++) {
stringBuffer.append(Integer.toString((arrayBytes[i] & 0xff) + 0x100, 16).substring(1));
}
return convertHexToBase64(stringBuffer.toString());
}
private static String convertHexToBase64(String hex) {
byte[] hexToBytes = DatatypeConverter.parseHexBinary(hex);
String base64 = Base64.getEncoder().encodeToString(hexToBytes);
System.out.println(base64);
return base64;
}
}
这是服务器从 Android 和 iPhone:
收到的 headersAndroid:
GET / HTTP/1.1
Host: 174.51.xxx.xx:9091
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: http://server.site88.net
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Linux; Android 5.0; SM-G900V Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.91 Mobile Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Sec-WebSocket-Key: IKTSyKHA8zclXsm2hFzm5Q==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
iPhone:
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: 174.51.xxx.xx:9091
Origin: http://server.site88.net
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: Sq0xOYhkomBmiyMbGwp/kQ==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 9_2_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13D15 Safari/601.1
我想通了。当我创建 headers 从服务器发送回浏览器时,我使用 "httpResponse.concat("\r\n\r\n")" 在 headers 的末尾添加换行符,这根本行不通。将其更改为 "httpResponse = httpResponse + "\r\n\r\n";"确实有效。