Javascript 客户端如何连接到 PHP 套接字服务器?

Posted

技术标签:

【中文标题】Javascript 客户端如何连接到 PHP 套接字服务器?【英文标题】:How can Javascript client connect to PHp socket Server? 【发布时间】:2011-10-13 03:55:25 【问题描述】:

您好,我有一个使用 php 编写的正在运行的套接字服务器。

服务器正在侦听连接。知道我的客户端(用 javascript 编写)将如何连接到服务器并向其发送数据吗?

PS:我只知道如何将 php 客户端连接到套接字服务器,但不确定如何连接 javascript 客户端。

感谢大家的宝贵时间。

【问题讨论】:

Javascript 是客户端脚本,它不提供打开套接字 afaik。在撰写本文时,我认为这是不可能的。 你在什么JS环境下运行?节点? WSH? ASP?浏览器插件?浏览器查看网页?还有什么? @Lionel Chan — JS 是一种通用编程语言,不提供大量 I/O 周期 — 来自主机环境。 @Quentin 是的,我对你的评论 +1,因为我忘记了 Node.JS 之类的东西 :) - 更多的是误读了这个问题 @quentin 浏览器查看网页 【参考方案1】:

我为客户使用标准的WebSocket API。 核心PHP socket 用于服务器端。

知道、发送和接收数据使用带有 websocket 的浏览器上的标头。但是代码 PHP 套接字,发送和接收没有标头,只是发送纯数据。

所以我们需要在socketing server端模拟header。

为了学习和知道怎么做,我写了这个清晰的示例代码,使用这个代码你可以发送一个短语到服务器并在客户端接收反向短语。

server.php

<?php
//Code by: Nabi KAZ <www.nabi.ir>

// set some variables
$host = "127.0.0.1";
$port = 5353;

// don't timeout!
set_time_limit(0);

// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0)or die("Could not create socket\n");

// bind socket to port
$result = socket_bind($socket, $host, $port)or die("Could not bind to socket\n");

// start listening for connections
$result = socket_listen($socket, 20)or die("Could not set up socket listener\n");

$flag_handshake = false;
$client = null;
do 
    if (!$client) 
        // accept incoming connections
        // client another socket to handle communication
        $client = socket_accept($socket)or die("Could not accept incoming connection\n");
    

    $bytes =  @socket_recv($client, $data, 2048, 0);
    if ($flag_handshake == false) 
        if ((int)$bytes == 0)
            continue;
        //print("Handshaking headers from client: ".$data."\n");
        if (handshake($client, $data, $socket)) 
            $flag_handshake = true;
        
    
    elseif($flag_handshake == true) 
        if ($data != "") 
            $decoded_data = unmask($data);
            print("< ".$decoded_data."\n");
            $response = strrev($decoded_data);
            socket_write($client, encode($response));
            print("> ".$response."\n");
            socket_close($client);
            $client = null;
            $flag_handshake = false;
        
    
 while (true);

// close sockets
socket_close($client);
socket_close($socket);

function handshake($client, $headers, $socket) 

    if (preg_match("/Sec-WebSocket-Version: (.*)\r\n/", $headers, $match))
        $version = $match[1];
    else 
        print("The client doesn't support WebSocket");
        return false;
    

    if ($version == 13) 
        // Extract header variables
        if (preg_match("/GET (.*) HTTP/", $headers, $match))
            $root = $match[1];
        if (preg_match("/Host: (.*)\r\n/", $headers, $match))
            $host = $match[1];
        if (preg_match("/Origin: (.*)\r\n/", $headers, $match))
            $origin = $match[1];
        if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $headers, $match))
            $key = $match[1];

        $acceptKey = $key.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
        $acceptKey = base64_encode(sha1($acceptKey, true));

        $upgrade = "HTTP/1.1 101 Switching Protocols\r\n".
            "Upgrade: websocket\r\n".
            "Connection: Upgrade\r\n".
            "Sec-WebSocket-Accept: $acceptKey".
            "\r\n\r\n";

        socket_write($client, $upgrade);
        return true;
     else 
        print("WebSocket version 13 required (the client supports version $version)");
        return false;
    


function unmask($payload) 
    $length = ord($payload[1]) & 127;

    if ($length == 126) 
        $masks = substr($payload, 4, 4);
        $data = substr($payload, 8);
    
    elseif($length == 127) 
        $masks = substr($payload, 10, 4);
        $data = substr($payload, 14);
    
    else 
        $masks = substr($payload, 2, 4);
        $data = substr($payload, 6);
    

    $text = '';
    for ($i = 0; $i < strlen($data); ++$i) 
        $text .= $data[$i] ^ $masks[$i % 4];
    
    return $text;


function encode($text) 
    // 0x1 text frame (FIN + opcode)
    $b1 = 0x80 | (0x1 & 0x0f);
    $length = strlen($text);

    if ($length <= 125)
        $header = pack('CC', $b1, $length);
    elseif($length > 125 && $length < 65536)$header = pack('CCS', $b1, 126, $length);
    elseif($length >= 65536)
    $header = pack('CCN', $b1, 127, $length);

    return $header.$text;

client.htm

<html>
<script>
//Code by: Nabi KAZ <www.nabi.ir>

var socket = new WebSocket('ws://localhost:5353');

// Open the socket
socket.onopen = function(event) 
    var msg = 'I am the client.';

    console.log('> ' + msg);

    // Send an initial message
    socket.send(msg);

    // Listen for messages
    socket.onmessage = function(event) 
        console.log('< ' + event.data);
    ;

    // Listen for socket closes
    socket.onclose = function(event) 
        console.log('Client notified socket has closed', event);
    ;

    // To close the socket....
    //socket.close()

;
</script>
<body>
<p>Please check the console log of your browser.</p>
</body>
</html>

手动:首先在 CLI 上运行 php server.php,然后在浏览器上打开 http://localhost/client.htm

你可以看到结果:

http://localhost/client.htm
> I am the client.
< .tneilc eht ma I

php server.php
< I am the client.
> .tneilc eht ma I

注意,这只是测试发送和接收数据的示例代码,对执行工作没有用处。

我建议你使用这些项目:

https://github.com/ghedipunk/PHP-Websocketshttps://github.com/esromneb/phpwebsockethttps://github.com/acbrandao/PHP/tree/master/wshttps://github.com/srchea/PHP-Push-WebSocket/http://socketo.me/

我还建议您阅读这些文章以了解更多详细信息:

http://www.abrandao.com/2013/06/websockets-html5-php/http://cuelogic.com/blog/php-and-html5-websocket-server-and-client-communication/http://srchea.com/build-a-real-time-application-using-html5-websockets

【讨论】:

【参考方案2】:

回答一个老问题,以防人们像我通过 Google 一样找到它。

现在几乎所有当代浏览器都支持 WebSocket Javascript API。通过 WS,浏览器中的客户端 JS 可以打开全双工套接字到用 PHP 或其他语言编写的服务器。服务器必须实现 WS 协议,但是现在有 PHP、Java 和其他语言的 WS 库。

在撰写本文时,WS 实现似乎仍然是一个移动的目标,但是,我目前正在使用与 WS/Java 服务器通信的 WS/JS 浏览器客户端,它似乎确实在工作。

建议使用您选择的服务器语言搜索 WS 实现。

希望这会有所帮助!

【讨论】:

【参考方案3】:

我不知道有什么可以为 JS 提供任意套接字功能。对Web Sockets 的支持有限(我认为这需要您修改服务器以符合空间)。如果做不到这一点,简单的XHR 可能会满足您的需求(这需要您修改服务器以充当 Web 服务)。如果服务在与页面不同的来源上运行,那么您将需要使用CORS 或使用诸如JSONP 之类的变通方法。

【讨论】:

【参考方案4】:

试试这个:

http://code.google.com/p/phpwebsocket/

【讨论】:

【参考方案5】:

简而言之 - 你不能这样做 - 让客户端代码打开套接字连接将是一个安全漏洞。

但是,您可以模拟 - 将您的数据作为 AJAX 请求发送到另一个 PHP 页面,然后使该 PHP 页面通过套接字进行通信。

2017 年更新

与此同时,websockets 变成了一个东西。请注意,websocket 协议与generic networking sockets 不同

【讨论】:

以上是关于Javascript 客户端如何连接到 PHP 套接字服务器?的主要内容,如果未能解决你的问题,请参考以下文章

如何将命名管道c#服务器连接到命名管道php客户端

如何仅使用 ajax 和 javascript 连接到 mysql 数据库?

任何人都可以告诉我如何在没有永久连接到 PHP 的情况下向客户端发送通知的方法

一步一步:如何进行 Xdebug 故障排除连接到客户端 IDE

将 javascript 连接到 php 套接字以与 Flash 通信

使用 javascript 和 php 连接到 phpmyadmin 上的数据库