2017-07-21 167 views
0

我在服务器端使用PHP web套接字。我目前只测试客户端和服务器之间的连接,所以我还没有配置套接字来响应特定的事件。这是基本的模板是什么样子:与PHP websocket的Socket.io握手?

#!/php -q 
<?php /* >php -q server.php */ 

error_reporting(E_ALL); 
set_time_limit(0); 
ob_implicit_flush(); 

$master = WebSocket("example.com",8080); 
$sockets = array($master); 
$users = array(); 
$debug = false; 

while(true){ 
    $changed = $sockets; 
    socket_select($changed,$write=NULL,$except=NULL,NULL); 
    foreach($changed as $socket){ 
    if($socket==$master){ 
     $client=socket_accept($master); 
     if($client<0){ console("socket_accept() failed"); continue; } 
     else{ connect($client); } 
    } 
    else{ 
     $bytes = @socket_recv($socket,$buffer,2048,0); 
     if($bytes==0){ disconnect($socket); } 
     else{ 
     $user = getuserbysocket($socket); 
     if(!$user->handshake){ dohandshake($user,$buffer); } 
     else{ process($user,$buffer); } 
     } 
    } 
    } 
} 

//--------------------------------------------------------------- 
function process($user,$msg){ 
    $action = unwrap($msg); 
    say("< ".$action); 
    switch($action){ 
case "hello" : send($user->socket,"hello human");      break; 
case "hi" : send($user->socket,"zup human");       break; 
case "name" : send($user->socket,"my name is Multivac, silly I know"); break; 
case "age" : send($user->socket,"I am older than time itself");  break; 
case "date" : send($user->socket,"today is ".date("Y.m.d"));   break; 
case "time" : send($user->socket,"server time is ".date("H:i:s"));  break; 
case "thanks": send($user->socket,"you're welcome");     break; 
case "bye" : send($user->socket,"bye");        break; 
default  : send($user->socket,$action." not understood");   break; 
    } 
} 

function send($client,$msg){ 
    say("> ".$msg); 
    $msg = wrap($msg); 
    socket_write($client,$msg,strlen($msg)); 
} 

function WebSocket($address,$port){ 
    $master=socket_create(AF_INET, SOCK_STREAM, SOL_TCP)  or die("socket_create() failed"); 
    socket_set_option($master, SOL_SOCKET, SO_REUSEADDR, 1) or die("socket_option() failed"); 
    socket_bind($master, $address, $port)     or die("socket_bind() failed"); 
    socket_listen($master,20)        or die("socket_listen() failed"); 
    echo "Server Started : ".date('Y-m-d H:i:s')."\n"; 
    echo "Master socket : ".$master."\n"; 
    echo "Listening on : ".$address." port ".$port."\n\n"; 
    return $master; 
} 

function connect($socket){ 
    global $sockets,$users; 
    $user = new User(); 
    $user->id = uniqid(); 
    $user->socket = $socket; 
    array_push($users,$user); 
    array_push($sockets,$socket); 
    console($socket." CONNECTED!"); 
} 

function disconnect($socket){ 
    global $sockets,$users; 
    $found=null; 
    $n=count($users); 
    for($i=0;$i<$n;$i++){ 
    if($users[$i]->socket==$socket){ $found=$i; break; } 
    } 
    if(!is_null($found)){ array_splice($users,$found,1); } 
    $index = array_search($socket,$sockets); 
    socket_close($socket); 
    console($socket." DISCONNECTED!"); 
    if($index>=0){ array_splice($sockets,$index,1); } 
} 

function dohandshake($user,$buffer){ 
    console("\nRequesting handshake..."); 
    console($buffer); 
    list($resource,$host,$origin,$strkey1,$strkey2,$data) = getheaders($buffer); 
    console("Handshaking..."); 

    $pattern = '/[^\d]*/'; 
    $replacement = ''; 
    $numkey1 = preg_replace($pattern, $replacement, $strkey1); 
    $numkey2 = preg_replace($pattern, $replacement, $strkey2); 

    $pattern = '/[^ ]*/'; 
    $replacement = ''; 
    $spaces1 = strlen(preg_replace($pattern, $replacement, $strkey1)); 
    $spaces2 = strlen(preg_replace($pattern, $replacement, $strkey2)); 

    if ($spaces1 == 0 || $spaces2 == 0 || $numkey1 % $spaces1 != 0 || $numkey2 % $spaces2 != 0) { 
    socket_close($user->socket); 
    console('failed'); 
    return false; 
    } 

    $ctx = hash_init('md5'); 
    hash_update($ctx, pack("N", $numkey1/$spaces1)); 
    hash_update($ctx, pack("N", $numkey2/$spaces2)); 
    hash_update($ctx, $data); 
    $hash_data = hash_final($ctx,true); 

    $upgrade = "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" . 
       "Upgrade: WebSocket\r\n" . 
       "Connection: Upgrade\r\n" . 
       "Sec-WebSocket-Origin: " . $origin . "\r\n" . 
       "Sec-WebSocket-Location: ws://" . $host . $resource . "\r\n" . 
       "\r\n" . 
       $hash_data; 

    socket_write($user->socket,$upgrade.chr(0),strlen($upgrade.chr(0))); 
    $user->handshake=true; 
    console($upgrade); 
    console("Done handshaking..."); 
    return true; 
} 

function getheaders($req){ 
    $r=$h=$o=null; 
    if(preg_match("/GET (.*) HTTP/" ,$req,$match)){ $r=$match[1]; } 
    if(preg_match("/Host: (.*)\r\n/" ,$req,$match)){ $h=$match[1]; } 
    if(preg_match("/Origin: (.*)\r\n/",$req,$match)){ $o=$match[1]; } 
    if(preg_match("/Sec-WebSocket-Key2: (.*)\r\n/",$req,$match)){ $key2=$match[1]; } 
    if(preg_match("/Sec-WebSocket-Key1: (.*)\r\n/",$req,$match)){ $key1=$match[1]; } 
    if(preg_match("/\r\n(.*?)\$/",$req,$match)){ $data=$match[1]; } 
    return array($r,$h,$o,$key1,$key2,$data); 
} 

function getuserbysocket($socket){ 
    global $users; 
    $found=null; 
    foreach($users as $user){ 
    if($user->socket==$socket){ $found=$user; break; } 
    } 
    return $found; 
} 

function  say($msg=""){ echo $msg."\n"; } 
function wrap($msg=""){ return chr(0).$msg.chr(255); } 
function unwrap($msg=""){ return substr($msg,1,strlen($msg)-2); } 
function console($msg=""){ global $debug; if($debug){ echo $msg."\n"; } } 

class User{ 
    var $id; 
    var $socket; 
    var $handshake; 
} 

?> 

,我想从我的雨燕客户端Socket.io连接到这个插座:

let io:SocketIOClient = SocketIOClient(socketURL: URL(string: "example.com:8080/server.php")!, config: [.log(true), .compress]) 

override func viewDidLoad() { 
    super.viewDidLoad() 

    self.io.on(clientEvent: .connect) { (data:[Any], ack:SocketAckEmitter) in 
     NSLog("Socket connected!") 
    } 
    self.io.on(clientEvent: .disconnect) { (data:[Any], ack:SocketAckEmitter) in 
     NSLog("Socket disconnected!") 
    } 
    self.io.connect() 
} 

我跑我的Mac上的终端服务器与SSH。 PHP网络套接字表示它正在监听连接,但它不响应socket.io连接。服务器和客户端都给我任何错误,所以我假设我错过了连接过程中的关键步骤。我想知道当你试图连接到一个PHP web套接字时,是否可以用Socket.IO swift客户端进行握手。这是一个兼容性问题还是我忘记了什么?顺便说一下,现在你可能已经注意到我对web套接字编程非常陌生(我不到一周前就发现了websocket),所以请原谅,如果这是一个真正的问题。我感谢任何帮助,我可以得到。谢谢!

回答

0

socket.io != webSocket。您无法将socket.io客户端连接到webSocket服务器。 Socket.io在webSocket上添加自己的协议。虽然socket.io在封面下使用webSocket传输,但如果您只有一个webSocket服务器,则客户端将无法连接。

您必须将webSocket客户端连接到webSocket服务器。或者,将一个socket.io客户端连接到一个socket.io服务器。

因此,就你的情况而言,如果你有一个socket.io客户端,那么你需要为你的服务器环境获取一个socket.io服务器,然后使用它。

+0

Socket.io服务器仅在Javascript(Node.js)中可用,我不熟悉这一点。我知道的唯一的服务器端语言是PHP,所以不可能仅仅替换连接的客户端呢?举个例子,Starscream说它是一个websocket客户端(不像Socket.io那样),所以我不能使用它来代替Socket.io? –

+0

@MarkCarols - socket.io服务器可用于许多其他环境(Java,PHP,C#等)。对于PHP,请参阅[this](https://www.google.com/search?q=socket.io+php&rlz=1C1CHFX_enUS515US515&oq=socket.io+php&aqs=chrome..69i57j0l5.1720j0j7&sourceid=chrome&ie=UTF-8)。浏览器内置了对webSocket的支持,所以你可以在浏览器中使用普通的webSocket。你只是不会有一些在这个答案中列出的socket.io功能:[从socket.io移动到原始websockets?](https://stackoverflow.com/questions/38546496/moving-from-socket-io -to-原始的WebSockets/38546537#38546537)。 – jfriend00

+0

谢谢!我会查看一些链接,看看哪一个最容易实现。 –