Ответ 1
Возможно, я нашел решение. Mobile Safari только сбой с веб-интерфейсами, когда вы устанавливаете прокси-сервер через Wi-Fi.
Я читал, что WebSockets работают на iOS 4.2 и выше. И я могу проверить, что действительно есть объект WebSocket. Но я не могу найти ни одного рабочего примера WebSocket, который работает на телефоне.
Например http://yaws.hyber.org/websockets_example.yaws приведет к сбою приложения Mobile Safari. Кто-нибудь получил WebSockets, успешно работающие на телефоне?
Возможно, я нашел решение. Mobile Safari только сбой с веб-интерфейсами, когда вы устанавливаете прокси-сервер через Wi-Fi.
Это поддерживается, но помните о стандарте, который реализует браузер Safari iOS, это не RFC 6455, а HyBi-00/Hixie-76.
Вы также можете проверить этот браузер: http://websocketstest.com/
Также проверьте этот отличный пост, который содержит большую часть информации относительно версий: fooobar.com/questions/4796/...
OBS!, это старый ответ. Я проверил веб-страницу, упомянутую в этом сообщении, в сочетании с browserstack.com:
Все, используя RFC 6455
У меня была аналогичная проблема, и я даже посмотрел на этот пост, чтобы найти исправление для него. Для меня это не имело никакого отношения к подключению Wi-Fi. Похоже, что это ошибка в iOS-реализации websockets (даже до текущей версии 5.1). Включив кучу отладки XCode, я обнаружил, что это имеет какое-то отношение к управлению памятью, потому что я получаю что-то вроде "сообщения, отправленного на освобожденный экземпляр". Скорее всего, существовал объект, у которого не было правильного подсчета ссылок, и был очищен слишком рано.
В этом блоге есть много отличной информации о симптомах проблемы и способах ее отладки, но нет обходного пути: http://dalelane.co.uk/blog/?p=1652
В конце концов, хотя, я нашел это обходное решение, и мое приложение почти полностью прекратило сбой теперь.
me = this // strange javascript convention
this.socket = new WebSocket(url);
// put onmessage function in setTimeout to get around ios websocket crash
this.socket.onmessage = function(evt) { setTimeout(function() {me.onMessageHandler(evt);}, 0); };
Я заставил их работать с Chrome и Safari, iPhone и iPad (и другими мобильными устройствами тоже, но я думаю, вы не против их). Вот код Javascript, который я использую:
<script language="javascript" type="text/javascript">
var wsUri = document.URL.replace("http", "ws");
var output;
var websocket;
function init()
{
output = document.getElementById("output");
wsConnect();
}
function wsConnect()
{
console.log("Trying connection to " + wsUri);
try
{
output = document.getElementById("output");
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt)
{
onOpen(evt)
};
websocket.onclose = function(evt)
{
onClose(evt)
};
websocket.onmessage = function(evt)
{
onMessage(evt)
};
websocket.onerror = function(evt)
{
onError(evt)
};
}
catch (e)
{
console.log("Exception " + e.toString());
}
}
function onOpen(evt)
{
alert("Connected to " + wsUri);
}
function onClose(evt)
{
alert("Disconnected");
}
function onMessage(evt)
{
alert('Received message : ' + evt.data);
}
function onError(evt)
{
alert("Error : " + evt.toString());
}
function doSend(message)
{
websocket.send(message);
}
window.addEventListener("load", init, false);
Отправка данных с клиента на сервер выполняется вызовом функции doSend(). Получение данных с сервера также работает, я проверил его с пользовательского сервера С++.
Вот рабочий пример
<!DOCTYPE html>
<meta charset="utf-8" />
<head>
<title>WebSocket Test</title>
<script language="javascript" type="text/javascript">
var websocket;
function OpenWebSocket()
{
try {
websocket = new WebSocket(document.getElementById("wsURL").value);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
}
catch(err) {
writeToScreen(err.message);
}
}
function CloseWebSocket()
{
websocket.close();
}
function FindWebSocketStatus()
{
try {
if (websocket.readyState == 1){
writeToScreen("Websocket connection is in open state")
}
else if (websocket.readyState == 0){
writeToScreen("Websocket connection is in connecting state")
}
else{
writeToScreen("Websocket connection is in close state")
}
}
catch(err) {
writeToScreen(err.message);
}
}
function FindWebSocketBufferedAmount(){
try {
writeToScreen(websocket.bufferedAmount)
}
catch(err) {
writeToScreen(err.message);
}
}
function SendMessageThroughSocket(){
doSend(document.getElementById("wsMessage").value);
}
function onOpen(evt)
{
writeToScreen("Socket Connection Opened");
}
function onClose(evt)
{
writeToScreen("Socket Connection Closed");
}
function onMessage(evt)
{
writeToScreen('<span style="color: blue;">SERVER RESPONSE: ' + evt.data+'</span>');
}
function onError(evt)
{
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}
function doSend(message)
{
try{
writeToScreen("CLIENT SENT: " + message);
websocket.send(message);
}
catch(err) {
writeToScreen(err.message);
}
}
function writeToScreen(message)
{
var output = document.getElementById("output");
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}
</script>
</title>
</head>
<body>
<table>
<tr>
<td>
WebSocket URL
</td>
<td>
<input type="text" id="wsURL" value="ws://echo.websocket.org/"/>
</td>
</tr>
<tr>
<td>
WebSocket Message
</td>
<td>
<input type="text" id="wsMessage" value="Hi"/>
</td>
</tr>
<tr>
<td colspan="2" style="text-align:left;">
<input type="button" value="Open Socket Connection" onclick="OpenWebSocket();"/>
</td>
</tr>
<tr>
<td colspan="2" style="text-align:left;">
<input type="button" value="Send Message" onclick="SendMessageThroughSocket();"/>
</td>
</tr>
<tr>
<td colspan="2" style="text-align:left;">
<input type="button" value="Close Socket Connection" onclick="CloseWebSocket();"/>
</td>
</tr>
<tr>
<td colspan="2" style="text-align:left;">
<input type="button" value="Find Socket Status" onclick="FindWebSocketStatus();"/>
</td>
</tr>
<tr>
<td colspan="2" style="text-align:left;">
<input type="button" value="Find Socket Buffered Amount" onclick="FindWebSocketBufferedAmount();"/>
</td>
</tr>
</table>
<div id="output"></div>
</body>
</html>
Создание собственного сервера сокетов также просто Просто установите Node.js и socket.io, затем перейдите к установке веб-сокета через npm
#!/usr/bin/env node
var WebSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function(request, response) {
console.log((new Date()) + ' Received request for ' + request.url);
response.writeHead(404);
response.end();
});
server.listen(8888, function() {
console.log((new Date()) + ' Server is listening on port 8888');
});
wsServer = new WebSocketServer({
httpServer: server,
// You should not use autoAcceptConnections for production
// applications, as it defeats all standard cross-origin protection
// facilities built into the protocol and the browser. You should
// *always* verify the connection origin and decide whether or not
// to accept it.
autoAcceptConnections: false
});
function originIsAllowed(origin) {
// put logic here to detect whether the specified origin is allowed.
return true;
}
wsServer.on('request', function(request) {
if (!originIsAllowed(request.origin)) {
// Make sure we only accept requests from an allowed origin
request.reject();
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
return;
}
var connection = request.accept();
console.log((new Date()) + ' Connection accepted.');
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log('Received Message: ' + message.utf8Data);
connection.sendUTF('Message received at server:'+message.utf8Data);
}
else if (message.type === 'binary') {
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
connection.sendBytes(message.binaryData);
}
});
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});
сохраните указанный выше файл как .js и запустите его как node filename.js из терминала или командной строки
Вышеприведенный файл похож на то, что мы сначала создали http-сервер, используя node, затем мы передаем созданный экземпляр http-сервера в Websocketserver, а затем в экземпляр Socket.iO
Я отлаживал аналогичную проблему и обнаружил, что если вы использовали https для получения веб-страницы, iOS будет ловушкой, если вы используете протокол a ws: в WebSocket. Если вы используете "wss:", все будет работать, и ловушек не будет.