긴 연결이란 무엇입니까?
친구들은 온라인 채팅 도구와 웹 온라인 채팅 도구를 많이 봤을 것입니다. 학교에는 익숙한 기능이 있습니다. 누군가가 귀하에게 답장을 보내면 즉시 웹사이트에 메시지가 나타납니다. 현재 페이지를 새로 고치지 않은 경우 Gmail에도 이 기능이 있습니다. 웹페이지가 새로 고쳐진 적이 없더라도 웹사이트에서 즉시 알려줍니다. 말하자면, 링크를 재사용하여 데이터와 지속적으로 상호작용한다는 사실은 모두가 잘 알고 있을 것입니다. 오늘날 많은 인터넷 비즈니스 시나리오에서는 게임, 채팅, 정보 푸시 등과 같은 긴 연결의 지원이 필요합니다. 따라서 많은 유사한 기능이 긴 연결과 분리될 수 없습니다. 이전 장에서는 PHP 소켓 통신을 소개했습니다. 이번 장에서는 PHP 소켓 긴 연결을 소개합니다.
긴 연결 및 짧은 링크
짧은 연결은 일반적으로 단일 항목의 데이터를 클라이언트에 적극적으로 "푸시"할 수 없습니다. 연결 훨씬 더 나은 점은 백엔드와 프런트엔드 기술의 조합을 사용하여 서버의 "정보 푸시" 기능을 실현할 수 있다는 것입니다. 데이터베이스에 업데이트가 있으면 백엔드 프로그램이 즉시 데이터를 "푸시"할 수 있습니다. , 여러 번 반복적으로 요청하는 대신 연결이 여러 번 설정되고 연결이 끊어집니다.
아마도 다음과 같은 설명이 있을 것입니다.
소위 롱 커넥션(Long Connection)이란 SOCKET 연결이 이루어진 후 사용 여부에 관계없이 연결을 유지하는 것을 말하며, 그러나 보안이 좋지 않습니다. 소위 짧은 연결 연결은 SOCKET 연결을 설정하고 데이터를 보내고 받은 후 즉시 연결을 끊는 것을 말합니다. 일반적으로 은행에서는 짧은 연결을 사용합니다.
긴 연결을 의미합니다. 현재 데이터 전송 중인지 수신 중인지에 관계없이 TCP 기반 통신에서 연결을 유지합니다. 짧은 연결이란 데이터 전송이 있을 때만 연결이 이루어지고, 클라이언트-서버 통신/데이터 전송이 완료된 후에 연결이 종료되는 것을 의미합니다.
통신 방법
각 네트워크 요소 사이에는 긴 연결과 짧은 연결의 두 가지 연결 방법이 있습니다. 소위 긴 연결은 TCP 연결을 유지하는 동안 여러 데이터 패킷이 지속적으로 전송될 수 있음을 의미합니다. 데이터 패킷이 전송되지 않으면 연결을 유지하기 위해 양쪽 당사자가 감지 패킷을 보내야 합니다. 짧은 연결은 통신 당사자가 데이터를 교환할 때 TCP 연결이 설정되는 것을 의미합니다. 즉, 각 TCP 연결은 한 쌍의 CMPP 메시지 전송만 완료합니다.
이 단계에서는 ISMG는 반드시 장기 연결 통신 방식을 사용해야 하며, SP와 ISMG 간에는 장기 연결 통신 방식을 사용하는 것이 좋습니다.
짧은 연결: 예를 들어 http만 연결하고 요청하고 닫는 경우 처리 시간이 짧을 경우 서버가 종료될 수 있습니다. 연결. 긴 연결: CMPP와 같은 일부 서비스는 서버에 대한 장기간 연결이 필요하며 일반적으로 사용자가 온라인으로 유지 관리해야 합니다.
소켓 긴 연결 구현
PHP 스크립트에 액세스할 때마다 모든 PHP 스크립트가 실행될 때까지 기다립니다. 지속적으로 실행하기 위해 스크립트가 필요한 경우 작업 목적을 달성하려면 PHP 긴 연결을 사용해야 합니다.
긴 연결을 사용하려면 소켓 캡슐화를 처리해야 합니다. 다음은 긴 소켓 연결을 수행하는 코드입니다.
예제 코드는 다음과 같습니다.
<?php $sfd = socket_create(AF_INET, SOCK_STREAM, 0); socket_bind($sfd, "0.0.0.0", 1234); socket_listen($sfd, 511); socket_set_option($sfd, SOL_SOCKET, SO_REUSEADDR, 1); socket_set_nonblock($sfd); $rfds = array($sfd); $wfds = array(); do{ $rs = $rfds; $ws = $wfds; $es = array(); $ret = socket_select($rs, $ws, $es, 3); //读取事件 foreach($rs as $fd){ if($fd == $sfd){ $cfd = socket_accept($sfd); socket_set_nonblock($cfd); $rfds[] = $cfd; echo "new client coming, fd=$cfd\n"; }else{ $msg = socket_read($fd, 1024); if($msg <= 0){ //close }else{ echo "on message, fd=$fd data=$msg\n"; } } } //写入事件 foreach($ws as $fd){ socket_write($fd, ........); } }while(true); ?>
다음은 효율성을 향상시킵니다.
<?php $sfd = stream_socket_server ('tcp://0.0.0.0:1234', $errno, $errstr); stream_set_blocking($sfd, 0); $base = event_base_new(); $event = event_new(); event_set($event, $sfd, EV_READ | EV_PERSIST, 'ev_accept', $base); event_base_set($event, $base); event_add($event); event_base_loop($base); function ev_accept($socket, $flag, $base) { $connection = stream_socket_accept($socket); stream_set_blocking($connection, 0); $buffer = event_buffer_new($connection, 'ev_read', NULL, 'ev_error', $connection); event_buffer_base_set($buffer, $base); event_buffer_timeout_set($buffer, 30, 30); event_buffer_watermark_set($buffer, EV_READ, 0, 0xffffff); event_buffer_priority_set($buffer, 10); event_buffer_enable($buffer, EV_READ | EV_PERSIST); } function ev_error($buffer, $error, $connection) { event_buffer_disable($buffer, EV_READ | EV_WRITE); event_buffer_free($buffer); fclose($connection); } function ev_read($buffer, $connection) { $read = event_buffer_read($buffer, 256); //do something.... } ?>
사람 수가 늘어나고 동시성이 증가함에 따라 단일 프로세스로는 더 이상 수요를 충족할 수 없습니다. 이 문제를 해결하기 위해 swoole, Workerman 등과 같은 기성 확장 및 라이브러리가 있습니까? 그런데 우리는 PHP를 사용하여 웹을 개발할 때 웹서버 관련 라이브러리를 개발에 사용하지 않죠? 우리는 단순한 메아리일 뿐입니다. 이런 복잡한 것들은 모두 nginx나 apache에 넘겨주고, 그들이 주저 없이 주도적으로 나서서 우리가 로직 작성에 집중할 수 있게 해준다. 소켓 서비스 작성은 웹 서비스 작성보다 더 발전된 것이 아닙니다. 모두 코딩 및 완료 요구사항입니다. 통신 계층은 고정되어 있지만 하나는 nginx에 의해 완료되고 다른 하나는 직접 완료됩니다. . 하지만 이제는 nginx+fpm, fooking+fpm=php 긴 연결과 유사한 솔루션을 사용하여 연결을 전달하고 라우터를 사용하여 메시지를 전달합니다.
코드는 다음과 같습니다.
<?php $sid = $_SERVER['SESSIONID'];//这是sessionid $data = file_get_contents("php://input");//这样就能拿到请求内容了 //想要返回消息只需要两步 header('Content-Length: 11');//返回给客户端字节数 echo "hello world"; //想要给别的用户发消息 include 'api.php'; $router = new RouterClient('router host', 'router port'); $router->sendMsg(用户sessionid, "fuck you"); //想要给所有人要消息 $router->sendAllMsg("fuck all"); //想给指定组发消息(类似redis的pub/sub) $router->publish("channel name", "fuck all"); ?>
[관련 튜토리얼 권장 사항]
1. "php.cn Dugu Jiujian (4 ) -php 비디오 튜토리얼 》
2. PHP 프로그래밍 입문부터 숙달까지 튜토리얼 전체
위 내용은 PHP 소켓에서 긴 연결을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!