Rumah >pembangunan bahagian belakang >tutorial php >Bagaimana untuk Membina Pelayan WebSocket dalam PHP?

Bagaimana untuk Membina Pelayan WebSocket dalam PHP?

Susan Sarandon
Susan Sarandonasal
2024-12-07 01:01:10390semak imbas

How to Build a WebSocket Server in PHP?

Cara Membuat Pelayan WebSocket dalam PHP

Mencipta pelayan WebSocket boleh menjadi tugas yang mencabar, terutamanya jika anda menghadapi kod yang sudah lapuk atau dokumentasi yang tidak lengkap . Berikut ialah penyelesaian terperinci untuk membimbing anda melalui proses:

Kod Bahagian Pelayan:

<?php

set_time_limit(0);
ob_implicit_flush();

$master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($master, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($master, "localhost", 12345);
socket_listen($master, 20);

$sockets = array($master);
$users = array();

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) {
        echo "socket_accept() failed\n";
        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 connect($socket) {
  global $sockets, $users;
  $user = new User();
  $user->id = uniqid();
  $user->socket = $socket;
  array_push($users, $user);
  array_push($sockets, $socket);
  echo $socket." CONNECTED!\n";
}

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);
  echo $socket." DISCONNECTED!\n";
  if ($index>=0) {
    array_splice($sockets, $index, 1);
  }
}

function dohandshake($user, $buffer) {
  $headers = getheaders($buffer);
  $acceptkey = base64_encode(sha1($headers[4] . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11",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($user->socket, $upgrade, strlen($upgrade));
  $user->handshake = true;
  echo "Done handshaking...\n";
}

function getheaders($req) {
  $r=$h=$u=$c=$key=$protocol=$version=$o=$data=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("/Upgrade: (.*)\r\n/", $req, $match)) {
    $u = $match[1];
  }
  if (preg_match("/Connection: (.*)\r\n/", $req, $match)) {
    $c = $match[1];
  }
  if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $req, $match)) {
    $key = $match[1];
  }
  if (preg_match("/Sec-WebSocket-Protocol: (.*)\r\n/", $req, $match)) {
    $protocol = $match[1];
  }
  if (preg_match("/Sec-WebSocket-Version: (.*)\r\n/", $req, $match)) {
    $version = $match[1];
  }
  if (preg_match("/Origin: (.*)\r\n/", $req, $match)) {
    $o = $match[1];
  }
  if (preg_match("/\r\n(.*?)$/", $req, $match)) {
    $data = $match[1];
  }
  return array($r,$h,$u,$c,$key,$protocol,$version,$o,$data);
}

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

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

?>

Pihak Pelanggan Kod:

var connection = new WebSocket('ws://localhost:12345');

connection.onopen = function () {
  connection.send('Ping');
};

connection.onerror = function (error) {
  console.log('WebSocket Error ' + error);
};

connection.onmessage = function (e) {
  console.log('Server: ' + e.data);
};

Penyelesaian masalah:

Jika anda menemui mesej ralat "Firefox tidak dapat mewujudkan sambungan ke pelayan di ws:// localhost:12345/", semak perkara berikut:

  • Pastikan kod pelayan anda berjalan pada port 12345.
  • Sahkan bahawa kod sebelah pelanggan anda bersambung ke nama hos dan port yang betul.
  • Pastikan kod anda melaksanakan prosedur jabat tangan WebSocket dengan betul seperti yang digariskan dalam spesifikasi RFC 6455.
  • Pastikan anda mengendalikan bingkai dan bingkai WebSocket dengan betul bertopeng.

Atas ialah kandungan terperinci Bagaimana untuk Membina Pelayan WebSocket dalam PHP?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn