在IOS

时间:2016-03-26 21:45:55

标签: javascript ios websocket server send

我一直在使用websockets在JavaScript(Java)和JavaScript客户端上工作,一切都可以在Android中找到,但是当我在iPhone上测试它时,JavaScript页面会挂起任何websocket.send方法。

在Android上,gameButton函数运行,输出“发送!”在页面上,服务器接收消息。在IOS上,gameButton函数输出类似“Input:u”的内容,但显然挂在connection.send上,并且不输出“Sent!”,并且服务器没有收到消息。 onopen功能永远不会在iPhone上调用,但它在Android上。有任何想法吗?如果您需要查看一些服务器代码,请告诉我们。

很抱歉长代码!

客户端的Javascript:

<!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接收的标头:

机器人:

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

1 个答案:

答案 0 :(得分:0)

我明白了。当我创建从服务器发送回浏览器的标题时,我使用“httpResponse.concat(”\ r \ n \ r \ n“)”“在标题的末尾添加换行符,这根本不起作用。将其更改为“httpResponse = httpResponse +”\ r \ n \ r \ n“;”确实有效。