>백엔드 개발 >PHP 튜토리얼 >PHP로 WebSocket 서버를 구축하는 방법은 무엇입니까?

PHP로 WebSocket 서버를 구축하는 방법은 무엇입니까?

Susan Sarandon
Susan Sarandon원래의
2024-12-07 01:01:10390검색

How to Build a WebSocket Server in PHP?

PHP에서 WebSocket 서버를 생성하는 방법

WebSocket 서버를 생성하는 것은 어려운 작업일 수 있으며, 특히 오래된 코드나 불완전한 문서가 있는 경우 더욱 그렇습니다. . 프로세스를 안내하는 자세한 솔루션은 다음과 같습니다.

서버 측 코드:

<?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;
}

?>

클라이언트 측 코드:

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);
};

문제 해결:

"Firefox가 ws://에서 서버에 연결할 수 없습니다"라는 오류 메시지가 나타나는 경우 localhost:12345/", 다음을 확인하세요.

  • 서버 코드가
  • 클라이언트측 코드가 올바른 호스트 이름과 포트에 연결되어 있는지 확인하세요.
  • 코드가 다음에 설명된 대로 WebSocket 핸드셰이크 절차를 올바르게 구현하고 있는지 확인하세요. RFC 6455 사양.
  • WebSocket 프레임과 마스킹.

위 내용은 PHP로 WebSocket 서버를 구축하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.