실행 방법 : 먼저 server.php와 index.html의 ip를 수정합니다 명령줄을 통해 [php path]php.exe "[file path]server.php" 를 실행한 후 index.html을 통해 index를 엽니다. 브라우저 .html
- include 'websocket.class.php';
- $config=array(
- 'address'=>'192.168. 0.200',
- 'port'=>'8000',
- 'event'=>'WSevent',//콜백 함수의 함수명
- 'log'=>true,
- );
- $websocket = new websocket($config);
- $websocket->run();
- function WSevent($type,$event){
- 전역 $websocket;
- if('in'==$type){
- $websocket->log('고객 항목 ID:'.$event['k']);
- }elseif('out'== $type ){
- $websocket->log('고객 종료 ID:'.$event['k']);
- }elseif('msg'==$type){
- $websocket -> ;log($event['k'].'메시지:'.$event['msg']);
- roboot($event['sign'],$event['msg']);
- }
- }
-
- function roboot($sign,$t){
- global $websocket;
- 스위치($t)
- {
- 케이스 'hello':
- $show='hello,GIt @ OSC';
- break;
- 케이스 '이름':
- $show='Robot';
- break;
- 케이스 '시간':
- $show='현재 시간:'.date('Y-m-d H:i:s');
- break;
- case '작별 인사':
- $show='( ^_^ )/ ~~ 안녕';
- $websocket->write($sign,'Robot:'.$show);
- $websocket->close($sign);
- return;
- break ;
- 사례 '왕이 호랑이를 덮다':
- $array = array('버섯을 넣은 닭고기 조림', '탑이 강귀를 흔든다', '모든 것이 수고했다');
- $show = $array[rand (0,2)];
- break;
- default:
- $show='( ⊙o⊙?) 이해가 안 되면 다음과 같이 말해 보세요: 안녕하세요, 이름, 이제 안녕, 천왕지호랑이.';
- }
- $websocket->write($sign,'Robot:'.$show);
- }
- ?> ;
-
코드 복사
- /*
- 클래스 websocket($config) 생성;
- $config 구조:
- $config=array(
- 'address'=>'192.168.0.200',//바인딩 주소
- 'port'=>'8000',//바인딩 포트
- 'event'=>'WSevent',// 함수 이름 콜백 함수
- 'log'=>true,//명령줄 표시 기록
- );
-
- 콜백 함수 반환 데이터 형식
- function WSevent($type,$event)
-
- $type 세 가지 유형의 문자열 이벤트 유형이 있습니다.
- 클라이언트 입력
- 클라이언트 연결 해제
- msg 클라이언트 메시지 도착
- 은 모두 소문자입니다.
-
- $event 배열
- $event['k'] 내장 사용자 목록의 사용자 ID;
- $event['sign'] 고객 로그인
- $event['msg'] 메시지 수신 $type=' msg'만 있음 이 정보
-
- 메서드:
- run()은
- search(label)를 실행하여 레이블의 ID를 탐색하고 얻습니다.
- close(label) 연결 끊기
- write( Mark, information) 푸시 정보
- idwrite(id, information) 푸시 정보
-
- 속성:
- $users 고객 목록
- 구조:
- $users=array(
- [User id]=> ;array('socket'=>[mark],'hand'=[악수 여부 - 부울 값]),
- [사용자 ID]=>arr....
- )
- */
-
- class websocket{
- 공개 $log;
- 공개 $event;
- 공개 $signets;
- 공개 $users
- 공개
- 공개; function __construct($config){
- if (substr(php_sapi_name(), 0, 3) !== 'cli') {
- die("명령줄 모드를 통해 실행하세요!");
- }
- error_reporting(E_ALL);
- set_time_limit(0);
- ob_implicit_flush();
- $this->event = $config['event'];
- $this- >log = $config['log'];
- $this->master=$this->WebSocket($config['address'], $config['port']);
- $ this-> ;sockets=array('s'=>$this->master);
- }
- 함수 WebSocket($address,$port){
- $server = 소켓_create(AF_INET, SOCK_STREAM, SOL_TCP) ;
- socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
- socket_bind($server, $address, $port);
- socket_listen($server);
- $this-> ;log( '듣기 시작: '.$address.' : '.$port);
- return $server;
- }
- function run(){
- while(true){
- $changes= $this->소켓;
- @socket_select($changes,$write=NULL,$Exception=NULL,NULL);
- foreach($changes as $sign){
- if($ sign== $this->마스터){
- $client=socket_accept($this->master);
- $this->sockets[]=$client;
- $user = 배열(
- 'socket'=>$client,
- 'hand'=>false,
- );
- $this->users[] = $user;
- $k=$ this-> ;search($client);
- $eventreturn = array('k'=>$k,'sign'=>$sign);
- $this->eventoutput('in' ,$eventreturn );
- }else{
- $len=socket_recv($sign,$buffer,2048,0);
- $k=$this->search($sign);
- $user= $this->users[$k];
- if($len<7){
- $this->close($sign);
- $eventreturn = array('k' => $k,'sign'=>$sign);
- $this->eventoutput('out',$eventreturn);
- 계속;
- }
- if(!$ this-> ;users[$k]['hand']){//핸드셰이크 없는 핸드셰이크
- $this->handshake($k,$buffer);
- }else{
- $buffer = $this- >uncode($buffer);
- $eventreturn = array('k'=>$k,'sign'=>$sign,'msg'=>$buffer);
- $this- >eventoutput('msg',$eventreturn);
- }
- }
- }
- }
- }
- 함수 검색($sign){//기호를 사용하여 Traverse를 사용하여 id
- foreach ($this->users as $k=>$v){
- if($sign==$v['socket'])
- return $k;
- }
- false 반환;
- }
- function close($sign){//기호로 연결 끊기
- $k=array_search($sign, $this->sockets);
- 소켓_close($ sign);
- unset($this->sockets[$k]);
- unset($this->users[$k]);
- }
- 함수 핸드셰이크($k, $buffer){
- $buf = substr($buffer,strpos($buffer,'Sec-WebSocket-Key:') 18);
- $key = Trim(substr($buf,0 ,strpos($) buf,"rn")));
- $new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));
- $new_message = "HTTP /1.1 101 전환 프로토콜rn";
- $new_message .= "업그레이드: websocketrn";
- $new_message .= "Sec-WebSocket-버전: 13rn";
- $new_message .= "연결: 업그레이드";
- $ new_message .= "Sec-WebSocket-Accept: " . $new_key . "rnrn";
- socket_write($this->users[$k]['socket'],$new_message,strlen($ new_message));
- $this->users[$k]['hand']=true;
- true를 반환합니다.
- }
- 함수 uncode($str){
- $mask = array();
- $data = '';
- $msg = unpack('H*',$str);
- $head = substr($msg[1],0,2);
- if (hexdec($head小贝) === 8) {
- $data = false;
- }else if (hexdec($head小贝) === 1){
- $mask[] = hexdec(substr($msg[1],4,2));
- $mask[ ] = hexdec(substr($msg[1],6,2));
- $mask[] = hexdec(substr($msg[1],8,2));
- $mask[] = hexdec(substr($msg[1],10,2));
- $s = 12;
- $e = strlen($msg[1])-2;
- $n = 0;
- for ($i=$s; $i<= $e; $i = 2) {
- $data .= chr($mask[$n%4]^hexdec(substr($msg[1) ],$i,2)));
- $n ;
- }
- }
- $data 반환;
- }
- 함수 코드($msg){
- $msg = preg_replace(array('/r$/','/n$ /','/rn$/',), '', $msg);
- $frame = array();
- $frame[0] = '81';
- $len = strlen($msg);
- $frame[1] = $len<16?'0'.dechex($len):dechex($len);
- $frame[2] = $this->ord_hex($msg);
- $data = implode('',$frame);
- return pack("H*", $data);
- }
- function ord_hex($data) {
- $msg = '';
- $l = strlen($data);
- for ($i= 0; $i $msg .= dechex(ord($data{$i}));
- }
- $msg를 반환합니다.
- }
-
- 함수 idwrite($id,$t){//일반적으로 id推送信息
- if(!$this->users[$id]['socket']){return false;}//没有这个标示
- $t=$this->code($t);
- return 소켓_write($this->users[$id]['socket'],$t, strlen($t));
- }
- 함수 write($k,$t){//일반적으로过标示推送信息
- $t=$this->code($t);
- return 소켓_write($k,$t,strlen($t));
- }
- 함수 eventoutput($type,$event){//事件回调
- call_user_func($this->event,$ type,$event);
- }
- 함수 로그($t){//控system台输출
- if($this->log){
- $t=$t."rn" ;
- fwrite(STDOUT, iconv('utf-8','gbk//IGNORE',$t));
- }
- }
- }
复제代码
|