이 문서의 내용은 PHP 소켓 프로그래밍에서 일반적으로 사용되는 기능과 간단한 C/S 상호 작용의 구현에 대한 내용입니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.
소켓 공식 설명:
네트워크 프로그래밍에서 가장 일반적으로 사용되는 솔루션은 클라이언트/서버(클라이언트/서버) 모델입니다. 이 시나리오에서 클라이언트 응용 프로그램은 서버 프로그램에서 서비스를 요청합니다. 서비스 프로그램은 일반적으로 잘 알려진 주소에서 서비스에 대한 요청을 수신합니다. 즉, 서비스 프로세스는 클라이언트가 서비스 주소에 대한 연결 요청을 할 때까지 휴면 상태로 유지됩니다. 이 순간, 서비스 프로그램은 "활성화"되어 클라이언트에게 서비스를 제공하며 클라이언트의 요청에 적절하게 반응합니다. 이 클라이언트/서버 모델의 네트워크 프로그래밍을 용이하게 하기 위해 1990년대 초에 Microsoft와 다른 여러 회사는 WINDOWS에서 일련의 네트워크 프로그래밍 인터페이스, 즉 Windows 소켓 사양을 공동으로 개발했습니다. 이는 네트워크 프로토콜이 아니라 네트워크입니다. 프로그래밍 인터페이스. Windows에서 여러 프로토콜을 지원하는 개방형 네트워크 프로그래밍 인터페이스 집합입니다. 이제 Winsock은 기본적으로 프로토콜 독립적이 되었습니다. Winsock을 사용하여 여러 프로토콜의 기능을 호출할 수 있지만 TCP/IP 프로토콜이 더 일반적으로 사용됩니다. 소켓은 실제로 소켓 인터페이스가 있는 모든 컴퓨터와 통신할 수 있는 통신 포트를 컴퓨터에 제공합니다. 애플리케이션은 네트워크에서 전송하고 이 소켓 인터페이스를 통해 정보를 받습니다
소켓을 네트워크의 다양한 컴퓨터 애플리케이션을 연결할 수 있는 파이프라인으로 간단히 이해하고 파이프라인의 A 끝에서 많은 데이터를 전송할 수 있습니다. , 파이프의 B 끝에서 나옵니다(C, D, E, F... 끝에서도 나올 수 있음).
참고
: 소켓 자체에는 실제 엔터티가 없으므로 소켓에 대한 개념만 알면 됩니다. 注意
:我们会在不同语境下使用不同的词语去修饰 socket,你只需要对它有个概念就好了,因为 socket 本身就没有真正意义上的实体
Socket 通信依次会进行 Socket 创建、 Socket 绑定、Socket 监听、Socket 收发、Socket 关闭几个阶段,下面我们列举出 PHP 网络编程中最常用也是必不可少的几个常用的函数进行进一步的说明。
TODO : 创建一个新的 socket 资源
函数原型: resource socket_create ( int $domain , int $type , int $protocol )
它包含三个参数,分别如下:
domain:AF_INET、AF_INET6、AF_UNIX,AF
的释义就 address family
,地址族的意思,我们常用的有 ipv4、ipv6
type: SOCK_STREAM、SOCK_DGRAM等,最常用的就是SOCK_STREAM
,基于字节流的SOCKET类型,也是TCP协议使用的类型
protocol: SOL_TCP、SOL_UDP 这个就是具体使用的传输协议,一般可靠的传输我们选择 TCP,游戏数据传输我们一般选用 UDP 协议
TODO : 将创建的 socket 资源绑定到具体的 ip 地址和端口
函数原型: bool socket_bind ( resource $socket , string $address [, int $port = 0 ] )
它包含三个参数,分别如下:
socket: 使用socket_create
创建的 socket 资源,可以认为是 socket 对应的 id
address: ip 地址
port: 监听的端口号,WEB 服务器默认80端口
TODO : 在具体的地址下监听 socket 资源的收发操作
函数原型: bool socket_listen ( resource $socket [, int $backlog = 0 ] )
它包含两个个参数,分别如下:
socket: 使用socket_create
创建的socket资源
backlog: 等待处理连接队列的最大长度
TODO : 监听之后,接收一个即将来临的新的连接,如果连接建立成功,将返回一个新的 socket 句柄(你可以理解为子进程,通常父进程用来接收新的连接,子进程负责具体的通信)
函数原型: resource socket_accept ( resource $socket )
socket: 使用socket_create
创建的socket资源
TODO : 将指定的数据发送到 对应的 socket 管道
函数原型: int socket_write ( resource $socket , string $buffer [, int $length ] )
socket: 使用socket_create
创建的socket资源
buffer: 写入到socket
资源中的数据
length: 控制写入到socket
资源中的buffer
的长度,如果长度大于buffer
的容量,则取buffer
resource 소켓_create(int $domain, int $type, int $protocol)
🎜각각 세 개의 매개 변수가 포함되어 있습니다. 🎜AF
의 의미는 주소 계열
입니다. 주소 패밀리의 의미로 우리는 일반적으로 ipv4, ipv6🎜SOCK_STREAM
입니다. 바이트 스트림에서 사용되는 TCP 프로토콜 유형🎜bool 소켓_bind(리소스 $socket, 문자열 $address [ , int $port = 0 ] )
🎜🎜다음과 같은 세 개의 매개변수가 포함되어 있습니다.🎜socket_create 는 소켓🎜
bool 소켓_listen(resource $socket [, int $backlog = 0 ] )
🎜 🎜다음과 같은 두 개의 매개변수가 포함되어 있습니다: 🎜socket_create
를 사용하여 생성된 소켓 리소스 >🎜리소스 소켓_accept(리소스 $socket )
🎜socket_create
🎜를 사용하여 생성된 소켓 리소스 li>int 소켓_write(resource $socket, string $buffer [, int $length ] )
🎜socket_create
🎜소켓
리소스🎜소켓
리소스에 기록된 버퍼
의 길이를 제어합니다. 버퍼
의 용량보다 크면 버퍼의 용량🎜TODO: 전송된 데이터 가져오기
함수 프로토타입: int 소켓_read(리소스 $socket , int $length )
int socket_read ( resource $socket , int $length )
socket: 使用socket_create
创建的socket资源
length: socket
资源中的buffer
的长度
TODO : 关闭 socket 资源
函数原型: void socket_close ( resource $socket )
socket: socket_accept
或者socket_create
产生的资源,不能用于stream
资源的关闭
由于创建一个SOCKET的流程总是 socket、bind、listen,所以PHP提供了一个非常方便的函数一次性创建、绑定端口、监听端口
函数原型: resource stream_socket_server ( string $local_socket [, int &$errno [, string &$errstr [, int $flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN [, resource $context ]]]] )
local_socket: 协议名://地址:端口号
errno: 错误码
errstr: 错误信息
flags: 只使用该函数的部分功能
context: 使用stream_context_create
函数创建的资源流上下文
基于上面的函数我们可以很方便的去构建 socket 通信程序(在这里我希望读者能单独建立一个目录比如socket
因为后续我们还会建立很多文件)我们先编辑一个服务端程序 server.php
,如下:
<?php date_default_timezone_set("Asia/Shanghai"); error_reporting(E_NOTICE ); /* 确保在连接客户端时不会超时 */ set_time_limit(0); $ip = '127.0.0.1'; $port = 8090; /* +------------------------------- * @socket通信整个过程 +------------------------------- * @socket_create * @socket_bind * @socket_listen * @socket_accept * @socket_read * @socket_write * @socket_close +-------------------------------- */ /*---------------- 以下操作都是手册上的 -------------------*/ if(($sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) < 0) { echo "socket_create() Why failure is:".socket_strerror($sock)."\n"; } if(($ret = socket_bind($sock,$ip,$port)) < 0) { echo "socket_bind() Why failure is:".socket_strerror($ret)."\n"; } if(($ret = socket_listen($sock,4)) < 0) { echo "socket_listen() Why failure is:".socket_strerror($ret)."\n"; } echo "Start time:".date('Y-m-d H:i:s') . PHP_EOL; echo "Listening at ".$ip.':'.$port.PHP_EOL; do { /* 创建新的连接 */ if (($msgsock = socket_accept($sock)) < 0) { echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n"; break; } else { # 连接成功输出 Socket id $i = (int)$msgsock; echo "welcome client $i"; # 向客户端通信(反馈) $msg ="连接成功!\n"; socket_write($msgsock, $msg, strlen($msg)); } socket_close($msgsock); } while (true); socket_close($sock); ?>
再编辑一个客户端程序client.php
,如下:
<?php set_time_limit(0); $port = 8090; $ip = "127.0.0.1"; /* +------------------------------- * 客户端 socket 连接整个过程 +------------------------------- * @socket_create * @socket_connect * @socket_write * @socket_read * @socket_close +-------------------------------- */ /** * @socket_connect:客户端发起套接字连接 * @param socket resource $socket 创建的$socket资源 * @param address string SOCK_STREAM IP地址|Unix套接字 * @param port int 端口 */ /** * @socket_create:创建并返回一个套接字 * @param domain string AF_INET IPV4 网络协议 * @param type string SOCK_STREAM 全双工字节流(可用的套接字类型) * @param protocol string SOL_TCP 具体协议(IPV4下的TCP协议) * @param return 套接字 */ $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if ($socket < 0) { echo "socket_create() failed: reason: " . socket_strerror($socket) . "\n"; }else { echo "try to connect '$ip' port: '$port'...\n"; } $result = socket_connect($socket, $ip, $port); #socket_connect的返回值应该是boolean值 if ($result < 0) { echo "socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n"; }else { # 连接成功输出提示信息 echo "connect successfully\n"; # 向服务端发送数据 socket_write($socket, " hello ", 1024); # 获取服务端数据 $result = socket_read($socket, 1024); echo "服务器回传数据为:" . $result; echo "CLOSE SOCKET...\n"; socket_close($socket); echo "CLOSE OK\n"; } ?>
然后我们打开终端(命令行)进入文件目录下依次执行:
php server.php php client.php
运行效果如下:
注意
socket_create
버퍼
의 길이를 사용하여 생성된 소켓 리소스 socket_close void 소켓_close(리소스 $socket )
소켓_accept code> 또는 <code>socket_create
에 의해 생성된 리소스는 stream
리소스🎜🎜🎜🎜stream_socket_server🎜🎜SOCKET 생성 프로세스가 항상 소켓이므로 닫는 데 사용할 수 없습니다. 따라서 PHP는 포트 생성, 바인딩, 포트 수신을 한 번에 할 수 있는 매우 편리한 기능을 제공합니다🎜🎜함수 프로토타입: resource stream_socket_server ( string $local_socket [, int &$errno [, string & $errstr [, int $flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN [, 리소스 $context ]]]] )
🎜socket
과 같은 별도의 디렉토리를 생성할 수 있기를 바랍니다.) 먼저 서버 프로그램 server.php는 다음과 같습니다.🎜rrreee🎜클라이언트 프로그램 <code>client.php
를 다음과 같이 편집합니다.🎜rrreee🎜그런 다음 터미널(명령줄)을 열고 순서대로 실행할 파일 디렉터리를 입력합니다.🎜 rrreee🎜실행 효과는 다음과 같습니다.🎜🎜 🎜🎜참고
서버가 수신 대기 중인 경우 프로세스가 일시 중지되고 다른 작업을 수행할 수 없습니다. . 클라이언트 프로그램을 실행하려면 다른 터미널을 시작해야 할 수도 있습니다🎜🎜관련 권장 사항: 🎜🎜🎜PHP와 MySql은 어떻게 백그라운드 데이터 읽기를 인식합니까?(코드) 🎜🎜🎜thinkphp5는 작업자 타이머를 사용하여 사이트 콘텐츠 코드를 정기적으로 크롤링합니다 🎜🎜 🎜🎜
위 내용은 PHP 소켓 프로그래밍에서 일반적으로 사용되는 함수 및 간단한 c/s 상호 작용 구현의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!