Я пытаюсь создать веб-сервер с socket.io для функции группового чата, которую мы реализуем в моем приложении.
Я использую основанную на Workerman PHP-библиотеку Socket.io, которая упрощает мне создание моих веб-сокетов / веб-серверов.
https://github.com/walkor/phpsocket.io
https://github.com/walkor/Workerman
Я следую примеру, который они предоставляют (https://github.com/walkor/phpsocket.io/tree/master/examples/chat). На локальном хосте (без SSL) работает отлично.
Тогда начинаются проблемы:
1 — При загрузке моего веб-сервера через Workerman, нужно ли указывать IP-адрес моего сервера (например, 521.241.241.21) или 0.0.0.0? Я все равно пытался поставить свой IP, и он не работал … работает только с 0.0.0.0 или 127.0.0.1.
2 — я пытаюсь заставить мой сервер иметь SSL. Вот что я пытаюсь сделать ниже:
Файл: start_web.php
use Workerman\Worker;
use Workerman\WebServer;
use Workerman\Autoloader;
use PHPSocketIO\SocketIO;
// composer autoload
require_once __DIR__ . '/vendor/autoload.php';
$context = array(
'ssl' => array(
'local_cert' => '/tmp/ssl/fullchain4.pem',
'local_pk' => '/tmp/ssl/privkey4.pem',
'verify_peer' => false
)
);
$web = new WebServer('https://0.0.0.0:2021', $context);
$web->addRoot('localhost', __DIR__."/public");
$web->transport = 'ssl';
if (!defined('GLOBAL_START')) {
Worker::runAll();
}
Файл: start_io.php
use Workerman\Worker;
use Workerman\WebServer;
use Workerman\Autoloader;
use PHPSocketIO\SocketIO;
// composer autoload
require_once __DIR__ . '/vendor/autoload.php';
// ssl context
$context = array(
'ssl' => array(
'local_cert' => '/tmp/ssl/fullchain4.pem',
'local_pk' => '/tmp/ssl/privkey4.pem',
'verify_peer' => false,
)
);
$io = new SocketIO(2020, $context);
$io->on('connection', function($socket){
$socket->addedUser = false;
// when the client emits 'new message', this listens and executes
$socket->on('new message', function ($data)use($socket){
// we tell the client to execute 'new message'
$socket->broadcast->emit('new message', array(
'username'=> $socket->username,
'message'=> $data
));
});
// when the client emits 'add user', this listens and executes
$socket->on('add user', function ($username) use($socket){
global $usernames, $numUsers;
// we store the username in the socket session for this client
$socket->username = $username;
// add the client's username to the global list
$usernames[$username] = $username;
++$numUsers;
$socket->addedUser = true;
$socket->emit('login', array(
'numUsers' => $numUsers
));
// echo globally (all clients) that a person has connected
$socket->broadcast->emit('user joined', array(
'username' => $socket->username,
'numUsers' => $numUsers
));
});
// when the client emits 'typing', we broadcast it to others
$socket->on('typing', function () use($socket) {
$socket->broadcast->emit('typing', array(
'username' => $socket->username
));
});
// when the client emits 'stop typing', we broadcast it to others
$socket->on('stop typing', function () use($socket) {
$socket->broadcast->emit('stop typing', array(
'username' => $socket->username
));
});
// when the user disconnects.. perform this
$socket->on('disconnect', function () use($socket) {
global $usernames, $numUsers;
// remove the username from global usernames list
if($socket->addedUser) {
unset($usernames[$socket->username]);
--$numUsers;
// echo globally that this client has left
$socket->broadcast->emit('user left', array(
'username' => $socket->username,
'numUsers' => $numUsers
));
}
});
});
if (!defined('GLOBAL_START')) {
Worker::runAll();
}
Чтобы поднять его, сожмите нужную команду и успешно без ошибок:
На стороне клиента у нас есть код:
<!DOCTYPE html>
<html>
<head>
<title>Teste de Chat Sala Virtual</title>
<link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css">
</head>
<body>
<textarea id="textareaMain" style="position: fixed; bottom: 0;" class="form-control" rows="4"></textarea>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="vendor/workerman/phpsocket.io/examples/chat/public/socket.io-client/socket.io.js"></script>
<script type="text/javascript" src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<script type="text/javascript">
var socket = io('https://dev.edufy.com.br:2021', {secure: true});
var connected = false;
// Socket events
// Whenever the server emits 'login', log the login message
socket.on('login', function (data) {
connected = true;
// Display the welcome message
console.log("Welcome to Socket.IO Chat – ");
});
// Whenever the server emits 'new message', update the chat body
socket.on('new message', function (data) {
console.log(data);
});
function setUsername () {
username = "eee";
// If the username is valid
if (username) {
// Tell the server your username
socket.emit('add user', username);
}
}
$("#textareaMain").keydown(function(e) {
if(e.which == 13) {
sendMessage ($("#textareaMain"));
}
});
// Sends a chat message
function sendMessage ($inputMessage) {
var message = $inputMessage.val();
// Prevent markup from being injected into the message
// if there is a non-empty message and a socket connection
if (message && connected) {
$inputMessage.val('');
// tell server to execute 'new message' and send along one parameter
socket.emit('new message', message);
} else {
console.log("Você não está conectado");
}
}
setUsername();
</script>
</body>
</html>
Мой клиент пытается подключиться к серверу несколько раз, однако безуспешно и с ошибками ниже:
Failed to load https://dev.edufy.com.br:2021/socket.io/?EIO=3&transport=polling&t=1530121185692-1: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://dev.edufy.com.br' is therefore not allowed access. The response had HTTP status code 404.
socket.io.js:2928 Cross-Origin Read Blocking (CORB) blocked cross-origin response https://dev.edufy.com.br:2021/socket.io/?EIO=3&transport=polling&t=1530121184069-0 with MIME type text/html. See https://www.chromestatus.com/feature/5629709824032768 for more details.
Request.create @ socket.io.js:2928
Request @ socket.io.js:2848
XHR.request @ socket.io.js:2779
XHR.doPoll @ socket.io.js:2809
Polling.poll @ socket.io.js:3201
Polling.doOpen @ socket.io.js:3145
Transport.open @ socket.io.js:2319
Socket.open @ socket.io.js:1749
Socket @ socket.io.js:1631
Socket @ socket.io.js:1566
Manager.open.Manager.connect @ socket.io.js:305
Manager @ socket.io.js:163
Manager @ socket.io.js:133
lookup @ socket.io.js:66
(anonymous) @ (index):16
socket.io.js:2928 Cross-Origin Read Blocking (CORB) blocked cross-origin response https://dev.edufy.com.br:2021/socket.io/?EIO=3&transport=polling&t=1530121185692-1 with MIME type text/html. See https://www.chromestatus.com/feature/5629709824032768 for more details.
Request.create @ socket.io.js:2928
Request @ socket.io.js:2848
XHR.request @ socket.io.js:2779
XHR.doPoll @ socket.io.js:2809
Polling.poll @ socket.io.js:3201
Polling.doOpen @ socket.io.js:3145
Transport.open @ socket.io.js:2319
Socket.open @ socket.io.js:1749
Socket @ socket.io.js:1631
Socket @ socket.io.js:1566
Manager.open.Manager.connect @ socket.io.js:305
(anonymous) @ socket.io.js:570
setTimeout (async)
Manager.reconnect @ socket.io.js:560
Manager.maybeReconnectOnOpen @ socket.io.js:286
(anonymous) @ socket.io.js:329
Emitter.emit @ socket.io.js:1341
Socket.onError @ socket.io.js:2173
(anonymous) @ socket.io.js:1780
Emitter.emit @ socket.io.js:1341
Transport.onError @ socket.io.js:2306
(anonymous) @ socket.io.js:2815
Emitter.emit @ socket.io.js:1341
Request.onError @ socket.io.js:2974
(anonymous) @ socket.io.js:2921
setTimeout (async)
xhr.onreadystatechange @ socket.io.js:2920
XMLHttpRequest.send (async)
Request.create @ socket.io.js:2928
Request @ socket.io.js:2848
XHR.request @ socket.io.js:2779
XHR.doPoll @ socket.io.js:2809
Polling.poll @ socket.io.js:3201
Polling.doOpen @ socket.io.js:3145
Transport.open @ socket.io.js:2319
Socket.open @ socket.io.js:1749
Socket @ socket.io.js:1631
Socket @ socket.io.js:1566
Manager.open.Manager.connect @ socket.io.js:305
Manager @ socket.io.js:163
Manager @ socket.io.js:133
lookup @ socket.io.js:66
(anonymous) @ (index):16
2socket.io.js:2928 OPTIONS https://dev.edufy.com.br:2021/socket.io/?EIO=3&transport=polling&t=1530121187674-2 404 (Not Found)
Обратите внимание, что он всегда делает два запроса:
Один из них с портом 2021, который попадает в ошибку CORS, а другой без порта 2021, который попадает в 404. Это правильно?
Задача ещё не решена.
Других решений пока нет …