PHP는 시스템 프로그래밍의 네트워크 소켓 및 IO 다중화를 실현합니다.
이 기사에서 공유한 내용은 PHP의 시스템 프로그래밍의 네트워크 소켓 및 IO 다중화에 관한 것입니다. 필요한 친구가 참조할 수 있습니다.
오랫동안 PHP는 거의 사용되지 않았습니다. 프로그래밍은 결국 스크립팅 언어이므로 효율성이 큰 병목 현상이 됩니다. 그러나 소켓 프로그래밍에 PHP를 사용할 수 없으며 PHP의 소켓 프로그래밍 성능이 너무 낮다고 말할 수도 없습니다. 예를 들어, 잘 알려진 PHP 소켓 프레임워크인 Workerman은 순수 PHP로 개발되었으며 뛰어난 성능을 자랑하므로 일부 환경에서는 PHP 소켓 프로그래밍도 그 기술을 뽐낼 수 있습니다.
PHP는 호출할 수 있는 C 언어 소켓 라이브러리의 메소드와 유사한 일련의 메소드를 제공합니다.
socket_accept — Accepts a connection on a socket socket_bind — 给套接字绑定名字 socket_clear_error — 清除套接字或者最后的错误代码上的错误 socket_close — 关闭套接字资源 socket_cmsg_space — Calculate message buffer size socket_connect — 开启一个套接字连接 socket_create_listen — Opens a socket on port to accept connections socket_create_pair — Creates a pair of indistinguishable sockets and stores them in an array socket_create — 创建一个套接字(通讯节点) socket_get_option — Gets socket options for the socket socket_getopt — 别名 socket_get_option socket_getpeername — Queries the remote side of the given socket which may either result in host/port or in a Unix filesystem path, dependent on its type socket_getsockname — Queries the local side of the given socket which may either result in host/port or in a Unix filesystem path, dependent on its type socket_import_stream — Import a stream socket_last_error — Returns the last error on the socket socket_listen — Listens for a connection on a socket socket_read — Reads a maximum of length bytes from a socket socket_recv — 从已连接的socket接收数据 socket_recvfrom — Receives data from a socket whether or not it is connection-oriented socket_recvmsg — Read a message socket_select — Runs the select() system call on the given arrays of sockets with a specified timeout socket_send — Sends data to a connected socket socket_sendmsg — Send a message socket_sendto — Sends a message to a socket, whether it is connected or not socket_set_block — Sets blocking mode on a socket resource socket_set_nonblock — Sets nonblocking mode for file descriptor fd socket_set_option — Sets socket options for the socket socket_setopt — 别名 socket_set_option socket_shutdown — Shuts down a socket for receiving, sending, or both socket_strerror — Return a string describing a socket error socket_write — Write to a socket
자세한 내용은 소켓에 대한 공식 PHP 매뉴얼을 확인하세요. http ://php .net/manual/zh/book.sockets.php
간단한 TCP 서버 예제 phptcpserver.php:
<?php $servsock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); // 创建一个socket if (FALSE === $servsock) { $errcode = socket_last_error(); fwrite(STDERR, "socket create fail: " . socket_strerror($errcode)); exit(-1); } if (!socket_bind($servsock, '127.0.0.1', 8888)) // 绑定ip地址及端口 { $errcode = socket_last_error(); fwrite(STDERR, "socket bind fail: " . socket_strerror($errcode)); exit(-1); } if (!socket_listen($servsock, 128)) // 允许多少个客户端来排队连接 { $errcode = socket_last_error(); fwrite(STDERR, "socket listen fail: " . socket_strerror($errcode)); exit(-1); } while (1) { $connsock = socket_accept($servsock); //响应客户端连接 if ($connsock) { socket_getpeername($connsock, $addr, $port); //获取连接过来的客户端ip地址和端口 echo "client connect server: ip = $addr, port = $port" . PHP_EOL; while (1) { $data = socket_read($connsock, 1024); //从客户端读取数据 if ($data === '') { //客户端关闭 socket_close($connsock); echo "client close" . PHP_EOL; break; } else { echo 'read from client:' . $data; $data = strtoupper($data); //小写转大写 socket_write($connsock, $data); //回写给客户端 } } } } socket_close($servsock);
이 서버를 시작하세요:
[root@localhost php]# php phptcpserver.php
그 후 서버가 차단되어 클라이언트가 연결될 때까지 기다립니다.
[root@localhost ~]# telnet 127.0.0.1 8888 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. ajdjajksdjkaasda AJDJAJKSDJKAASDA 小明哈哈哈哈笑 小明哈哈哈哈笑 小明efsfsdfsdf了哈哈哈 小明EFSFSDFSDF了哈哈哈
서버 출력:
[root@localhost php]# php phptcpserver.php client connect server: ip = 127.0.0.1, port = 50398 read from client:ajdjajksdjkaasda read from client:小明哈哈哈哈笑 read from client:小明efsfsdfsdf了哈哈哈
하지만 실제로 이 TCP 서버에는 한 번에 한 클라이언트의 연결과 데이터 전송만 처리할 수 있다는 문제가 있습니다. 클라이언트가 데이터를 전송하지 않으면 TCP 서버는 읽기 차단 상태가 되어 더 이상 다른 클라이언트의 연결 요청을 처리할 수 없습니다.
이 문제를 해결하는 한 가지 방법은 다중 프로세스 서버를 사용하는 것입니다. 클라이언트가 연결될 때마다 서버는 클라이언트와의 데이터 전송을 담당하는 하위 프로세스를 열고 상위 프로세스는 여전히 클라이언트의 프로세스를 모니터링합니다. 하지만 프로세스 시작 비용이 많이 듭니다. 이 다중 프로세스 메커니즘은 분명히 높은 동시성을 지원할 수 없습니다.
또 다른 해결책은 IO 멀티플렉싱 메커니즘을 사용하고 PHP에서 제공하는 소켓_select 메서드를 사용하는 것입니다. 소켓 중 하나의 상태가 쓰기 불가능에서 쓰기 가능으로, 읽을 수 없음에서 읽기 가능으로 변경되는 경우를 모니터링할 수 있습니다. , 이 메소드는 소켓을 처리하고, 클라이언트 연결을 처리하고, 읽기 및 쓰기 작업 등을 수행할 수 있도록 반환됩니다. PHP 문서에서 소켓_select에 대한 소개를 살펴보겠습니다
socket_select — Runs the select() system call on the given arrays of sockets with a specified timeout 说明 int socket_select ( array &$read , array &$write , array &$except , int $tv_sec [, int $tv_usec = 0 ] ) socket_select() accepts arrays of sockets and waits for them to change status. Those coming with BSD sockets background will recognize that those socket resource arrays are in fact the so-called file descriptor sets. Three independent arrays of socket resources are watched. You do not need to pass every array to socket_select(). You can leave it out and use an empty array or NULL instead. Also do not forget that those arrays are passed by reference and will be modified after socket_select() returns. 返回值 On success socket_select() returns the number of socket resources contained in the modified arrays, which may be zero if the timeout expires before anything interesting happens. On error FALSE is returned. The error code can be retrieved with socket_last_error().
대략 번역:
socket_select --- 주어진 소켓 배열 세트에서 select() 시스템 호출을 실행합니다. 특정 시간 초과.
socket_select()는 여러 소켓 배열을 매개변수로 받아들이고 상태 변경을 수신합니다.
이 BSD 스코켓은 이러한 소켓 리소스 배열이 실제로 파일 설명자의 모음임을 인식하는 기능을 기반으로 합니다.
세 개의 서로 다른 소켓 리소스 배열이 동시에 모니터링됩니다.
이 세 가지 리소스 배열은 필수가 아닙니다. 빈 배열이나 NULL을 매개 변수로 사용할 수 있습니다. 이 세 가지 배열은 함수가 반환된 후 해당 배열의 값이 전달됩니다. 변화가 되십시오.
socket_select()는 이 세 배열에서 상태가 변경된 총 소켓 수를 성공적으로 반환합니다. 시간 초과가 설정되어 있고 시간 초과 내에 상태 변경이 없으면 이 함수는 0을 반환합니다. 오류가 발생하면 FALSE를 반환하면 소켓_last_error()를 사용할 수 있습니다. 오류 코드를 가져옵니다. T phptcpserver.php 코드 이전에 소켓_select()를 사용하여 최적화:
<?php $servsock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); // 创建一个socket if (FALSE === $servsock) { $errcode = socket_last_error(); fwrite(STDERR, "socket create fail: " . socket_strerror($errcode)); exit(-1); } if (!socket_bind($servsock, '127.0.0.1', 8888)) // 绑定ip地址及端口 { $errcode = socket_last_error(); fwrite(STDERR, "socket bind fail: " . socket_strerror($errcode)); exit(-1); } if (!socket_listen($servsock, 128)) // 允许多少个客户端来排队连接 { $errcode = socket_last_error(); fwrite(STDERR, "socket listen fail: " . socket_strerror($errcode)); exit(-1); } /* 要监听的三个sockets数组 */ $read_socks = array(); $write_socks = array(); $except_socks = NULL; // 注意 php 不支持直接将NULL作为引用传参,所以这里定义一个变量 $read_socks[] = $servsock; while (1) { /* 这两个数组会被改变,所以用两个临时变量 */ $tmp_reads = $read_socks; $tmp_writes = $write_socks; // int socket_select ( array &$read , array &$write , array &$except , int $tv_sec [, int $tv_usec = 0 ] ) $count = socket_select($tmp_reads, $tmp_writes, $except_socks, NULL); // timeout 传 NULL 会一直阻塞直到有结果返回 foreach ($tmp_reads as $read) { if ($read == $servsock) { /* 有新的客户端连接请求 */ $connsock = socket_accept($servsock); //响应客户端连接, 此时不会造成阻塞 if ($connsock) { socket_getpeername($connsock, $addr, $port); //获取远程客户端ip地址和端口 echo "client connect server: ip = $addr, port = $port" . PHP_EOL; // 把新的连接sokcet加入监听 $read_socks[] = $connsock; $write_socks[] = $connsock; } } else { /* 客户端传输数据 */ $data = socket_read($read, 1024); //从客户端读取数据, 此时一定会读到数组而不会产生阻塞 if ($data === '') { //移除对该 socket 监听 foreach ($read_socks as $key => $val) { if ($val == $read) unset($read_socks[$key]); } foreach ($write_socks as $key => $val) { if ($val == $read) unset($write_socks[$key]); } socket_close($read); echo "client close" . PHP_EOL; } else { socket_getpeername($read, $addr, $port); //获取远程客户端ip地址和端口 echo "read from client # $addr:$port # " . $data; $data = strtoupper($data); //小写转大写 if (in_array($read, $tmp_writes)) { //如果该客户端可写 把数据回写给客户端 socket_write($read, $data); } } } } } socket_close($servsock);
이제 이 TCP 서버는 여러 클라이언트가 동시에 연결할 수 있도록 지원합니다. 테스트:
서버 측:
R
[root@localhost php]# php phptcpserver.php client connect server: ip = 127.0.0.1, port = 50404 read from client # 127.0.0.1:50404 # hello world client connect server: ip = 127.0.0.1, port = 50406 read from client # 127.0.0.1:50406 # hello PHP read from client # 127.0.0.1:50404 # 少小离家老大回 read from client # 127.0.0.1:50404 # 乡音无改鬓毛衰 read from client # 127.0.0.1:50406 # 老当益壮, read from client # 127.0.0.1:50406 # 宁移白首之心 client close client connect server: ip = 127.0.0.1, port = 50408
.... socket_getpeername($read, $addr, $port); //获取远程客户端ip地址和端口 echo "read from client # $addr:$port # " . $data; $response = "HTTP/1.1 200 OK\r\n"; $response .= "Server: phphttpserver\r\n"; $response .= "Content-Type: text/html\r\n"; $response .= "Content-Length: 3\r\n\r\n"; $response .= "ok\n"; if (in_array($read, $tmp_writes)) { //如果该客户端可写 把数据回写给客户端 socket_write($read, $response); socket_close($read); // 主动关闭客户端连接 //移除对该 socket 监听 foreach ($read_socks as $key => $val) { if ($val == $read) unset($read_socks[$key]); } foreach ($write_socks as $key => $val) { if ($val == $read) unset($write_socks[$key]); } } .....
서버 측 출력:
5,000QPS가 넘는 모습이 조금 기대되시나요?^^.
PHP는 세계 최고의 언어입니다!
위 내용은 PHP는 시스템 프로그래밍의 네트워크 소켓 및 IO 다중화를 실현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











PHP 8.4는 상당한 양의 기능 중단 및 제거를 통해 몇 가지 새로운 기능, 보안 개선 및 성능 개선을 제공합니다. 이 가이드에서는 Ubuntu, Debian 또는 해당 파생 제품에서 PHP 8.4를 설치하거나 PHP 8.4로 업그레이드하는 방법을 설명합니다.

VS Code라고도 알려진 Visual Studio Code는 모든 주요 운영 체제에서 사용할 수 있는 무료 소스 코드 편집기 또는 통합 개발 환경(IDE)입니다. 다양한 프로그래밍 언어에 대한 대규모 확장 모음을 통해 VS Code는

숙련된 PHP 개발자라면 이미 그런 일을 해왔다는 느낌을 받을 것입니다. 귀하는 상당한 수의 애플리케이션을 개발하고, 수백만 줄의 코드를 디버깅하고, 여러 스크립트를 수정하여 작업을 수행했습니다.

이 튜토리얼은 PHP를 사용하여 XML 문서를 효율적으로 처리하는 방법을 보여줍니다. XML (Extensible Markup Language)은 인간의 가독성과 기계 구문 분석을 위해 설계된 다목적 텍스트 기반 마크 업 언어입니다. 일반적으로 데이터 저장 AN에 사용됩니다

JWT는 주로 신분증 인증 및 정보 교환을 위해 당사자간에 정보를 안전하게 전송하는 데 사용되는 JSON을 기반으로 한 개방형 표준입니다. 1. JWT는 헤더, 페이로드 및 서명의 세 부분으로 구성됩니다. 2. JWT의 작업 원칙에는 세 가지 단계가 포함됩니다. JWT 생성, JWT 확인 및 Parsing Payload. 3. PHP에서 인증에 JWT를 사용하면 JWT를 생성하고 확인할 수 있으며 사용자 역할 및 권한 정보가 고급 사용에 포함될 수 있습니다. 4. 일반적인 오류에는 서명 검증 실패, 토큰 만료 및 대형 페이로드가 포함됩니다. 디버깅 기술에는 디버깅 도구 및 로깅 사용이 포함됩니다. 5. 성능 최적화 및 모범 사례에는 적절한 시그니처 알고리즘 사용, 타당성 기간 설정 합리적,

문자열은 문자, 숫자 및 기호를 포함하여 일련의 문자입니다. 이 튜토리얼은 다른 방법을 사용하여 PHP의 주어진 문자열의 모음 수를 계산하는 방법을 배웁니다. 영어의 모음은 A, E, I, O, U이며 대문자 또는 소문자 일 수 있습니다. 모음이란 무엇입니까? 모음은 특정 발음을 나타내는 알파벳 문자입니다. 대문자와 소문자를 포함하여 영어에는 5 개의 모음이 있습니다. a, e, i, o, u 예 1 입력 : String = "Tutorialspoint" 출력 : 6 설명하다 문자열의 "Tutorialspoint"의 모음은 u, o, i, a, o, i입니다. 총 6 개의 위안이 있습니다

정적 바인딩 (정적 : :)는 PHP에서 늦은 정적 바인딩 (LSB)을 구현하여 클래스를 정의하는 대신 정적 컨텍스트에서 호출 클래스를 참조 할 수 있습니다. 1) 구문 분석 프로세스는 런타임에 수행됩니다. 2) 상속 관계에서 통화 클래스를 찾아보십시오. 3) 성능 오버 헤드를 가져올 수 있습니다.

PHP의 마법 방법은 무엇입니까? PHP의 마법 방법은 다음과 같습니다. 1. \ _ \ _ Construct, 객체를 초기화하는 데 사용됩니다. 2. \ _ \ _ 파괴, 자원을 정리하는 데 사용됩니다. 3. \ _ \ _ 호출, 존재하지 않는 메소드 호출을 처리하십시오. 4. \ _ \ _ get, 동적 속성 액세스를 구현하십시오. 5. \ _ \ _ Set, 동적 속성 설정을 구현하십시오. 이러한 방법은 특정 상황에서 자동으로 호출되어 코드 유연성과 효율성을 향상시킵니다.
