PHP SOCKET 프로그래밍_php 기술에 대한 자세한 설명
1. 사전 지식
PHP의 소켓 모듈을 사용하여 어떤 작업을 수행하는 사람은 거의 본 적이 없습니다. 아마도 모든 사람이 이를 스크립팅 언어의 범위 내에 두지만 실제로 PHP의 소켓 모듈은 ftplist, http post 제출, smtp 제출을 포함하여 많은 작업을 수행할 수 있습니다. , 그룹 패키지 및 특수 메시지의 상호 작용(예: smpp 프로토콜), whois 쿼리. 다음은 보다 일반적인 쿼리 중 일부입니다.
특히 PHP의 소켓 확장 라이브러리가 할 수 있는 일은 C보다 나쁘지 않습니다.
PHP 소켓 연결 기능
1. 커널에 소켓이 통합되어 있습니다
이 일련의 기능은 활성 연결만 수행할 수 있으며 포트 모니터링 관련 기능은 구현할 수 없습니다. 그리고 4.3.0 이전에는 모든 소켓 연결이 차단 모드에서만 작동할 수 있었습니다.
이 일련의 기능에는
이 포함됩니다.
fsockopen, pfsockopen
이 두 가지 기능에 대한 자세한 내용은 php.net 사용자 매뉴얼을 확인하세요
이 리소스의 경우 fgets(), fwrite(), fclose() 등과 같이 파일에서 작동하는 거의 모든 함수를 사용할 수 있습니다. 모든 함수는 이러한 함수를 따라 네트워크 정보를 확인합니다. 흐름. 예:
fread()는 파일 포인터 핸들에서 최대 길이 바이트까지 읽습니다. 이 함수는 length 바이트를 읽거나, EOF에 도달하거나, (네트워크 스트림의 경우) 패킷을 사용할 수 있게 되면(둘 중 먼저 발생하는 경우) 파일 읽기를 중지합니다.
네트워크 흐름의 경우 완전한 패킷을 얻었을 때 중지에 주의해야 함을 알 수 있습니다.
2. php 확장 모듈에서 제공하는 소켓 기능입니다.
php4.x에는 모듈 확장=php_sockets.dll이 있고 Linux에는 확장=php_sockets.so가 있습니다.
이 모듈이 켜져 있으면 PHP가 청취 포트, 차단 모드와 비차단 모드 간 전환, 다중 클라이언트 대화형 처리 등을 포함한 강력한 소켓 기능을 가지고 있음을 의미합니다.
이 시리즈의 기능 목록은 http://www.php.net/manual/en/ref.sockets.php
를 참조하세요.
이 목록을 읽은 후, 그것이 매우 풍부하다고 생각하십니까? 하지만 이 모듈은 아직 여러 곳에서 매우 어리고 미성숙한 상태이며 관련 참고 문서가 거의 없다는 점은 아쉽습니다.(
저도 연구 중이라 자세한 내용은 당분간 다루지 않고 참고글만 드리겠습니다
http://www.zend.com/pecl/tutorials/sockets.php
2. PHP 소켓 확장 사용
서버측 코드:
<?php /** * File name server.php * 服务器端代码 * * @author guisu.huang * @since 2012-04-11 * */ //确保在连接客户端时不会超时 set_time_limit(0); //设置IP和端口号 $address = "127.0.0.1"; $port = 2046; //调试的时候,可以多换端口来测试程序! /** * 创建一个SOCKET * AF_INET=是ipv4 如果用ipv6,则参数为 AF_INET6 * SOCK_STREAM为socket的tcp类型,如果是UDP则使用SOCK_DGRAM */ $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("socket_create() 失败的原因是:" . socket_strerror(socket_last_error()) . "/n"); //阻塞模式 socket_set_block($sock) or die("socket_set_block() 失败的原因是:" . socket_strerror(socket_last_error()) . "/n"); //绑定到socket端口 $result = socket_bind($sock, $address, $port) or die("socket_bind() 失败的原因是:" . socket_strerror(socket_last_error()) . "/n"); //开始监听 $result = socket_listen($sock, 4) or die("socket_listen() 失败的原因是:" . socket_strerror(socket_last_error()) . "/n"); echo "OK\nBinding the socket on $address:$port ... "; echo "OK\nNow ready to accept connections.\nListening on the socket ... \n"; do { // never stop the daemon //它接收连接请求并调用一个子连接Socket来处理客户端和服务器间的信息 $msgsock = socket_accept($sock) or die("socket_accept() failed: reason: " . socket_strerror(socket_last_error()) . "/n"); //读取客户端数据 echo "Read client data \n"; //socket_read函数会一直读取客户端数据,直到遇见\n,\t或者 字符.PHP脚本把这写字符看做是输入的结束符. $buf = socket_read($msgsock, 8192); echo "Received msg: $buf \n"; //数据传送 向客户端写入返回结果 $msg = "welcome \n"; socket_write($msgsock, $msg, strlen($msg)) or die("socket_write() failed: reason: " . socket_strerror(socket_last_error()) ."/n"); //一旦输出被返回到客户端,父/子socket都应通过socket_close($msgsock)函数来终止 socket_close($msgsock); } while (true); socket_close($sock);
클라이언트 코드:
<?php /** * File name:client.php * 客户端代码 * * @author guisu.huang * @since 2012-04-11 */ set_time_limit(0); $host = "127.0.0.1"; $port = 2046; $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)or die("Could not create socket\n"); // 创建一个Socket $connection = socket_connect($socket, $host, $port) or die("Could not connet server\n"); // 连接 socket_write($socket, "hello socket") or die("Write failed\n"); // 数据传送 向服务器发送消息 while ($buff = socket_read($socket, 1024, PHP_NORMAL_READ)) { echo("Response was:" . $buff . "\n"); } socket_close($socket);
cli를 사용하여 서버 시작:
php 서버.php
여기에서 소켓_읽기 기능에 주목하세요:
선택적 유형 매개변수는 명명된 상수입니다:
PHP_BINARY_READ - 시스템 recv() 함수를 사용합니다. 바이너리 데이터 읽기를 위한 보안. (PHP에서 > "기본값 = 4.1.0)
PHP_NORMAL_READ - 읽기가 n에서 중지되거나
(PHP <= 4.0.6의 기본값)
PHP_NORMAL_READ 매개변수의 경우, 서버의 응답 결과에 n이 없는 경우. 원인 소켓_read(): 소켓에서 읽을 수 없습니다
3. PHP 소켓 내부 소스코드
PHP 내부 소스코드부터 PHP가 제공하는 소켓 프로그래밍은 소켓에 레이어를 추가해 바인딩, 리슨 등의 기능을 더 간단하고 쉽게 호출할 수 있도록 해준다. 그러나 일부 비즈니스 로직 프로그램은 여전히 프로그래머가 직접 구현해야 합니다.
아래에서는 PHP의 내부 구현을 설명하기 위해 소켓_create의 소스 코드 구현을 사용합니다.
앞서 우리는 PHP의 소켓이 확장된 방식으로 구현된다고 언급했습니다. 소스 코드의 ext 디렉토리에서 소켓 디렉토리를 찾습니다. 이 디렉토리는 PHP의 소켓 구현을 저장합니다. PHP_FUNCTION(socket_create)을 직접 검색하고 소켓.c 파일에서 이 함수의 구현을 찾으세요. 코드는 다음과 같습니다.
/* {{{ proto resource socket_create(int domain, int type, int protocol) U Creates an endpoint for communication in the domain specified by domain, of type specified by type */ PHP_FUNCTION(socket_create) { long arg1, arg2, arg3; php_socket *php_sock = (php_socket*)emalloc(sizeof(php_socket)); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &arg1, &arg2, &arg3) == FAILURE) { efree(php_sock); return; } if (arg1 != AF_UNIX #if HAVE_IPV6 && arg1 != AF_INET6 #endif && arg1 != AF_INET) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket domain [%ld] specified for argument 1, assuming AF_INET", arg1); arg1 = AF_INET; } if (arg2 > 10) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket type [%ld] specified for argument 2, assuming SOCK_STREAM", arg2); arg2 = SOCK_STREAM; } php_sock->bsd_socket = socket(arg1, arg2, arg3); php_sock->type = arg1; if (IS_INVALID_SOCKET(php_sock)) { SOCKETS_G(last_error) = errno; php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create socket [%d]: %s", errno, php_strerror(errno TSRMLS_CC)); efree(php_sock); RETURN_FALSE; } php_sock->error = 0; php_sock->blocking = 1; 1257,1-8 61% ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket); }
Zend API는 실제로 PHP에서 사용할 수 있도록 c 함수 소켓을 래핑합니다. C 소켓 프로그래밍에서는 다음 방법을 사용하여 소켓을 초기화합니다.
//初始化Socket if( (socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){ printf("create socket error: %s(errno: %d)\n",strerror(errno),errno); exit(0); }
4. socket函数
函数名 描述
socket_accept() 接受一个Socket连接
socket_bind() 把socket绑定在一个IP地址和端口上
socket_clear_error() 清除socket的错误或最后的错误代码
socket_close() 关闭一个socket资源
socket_connect() 开始一个socket连接
socket_create_listen() 在指定端口打开一个socket监听
socket_create_pair() 产生一对没有差别的socket到一个数组里
socket_create() 产生一个socket,相当于产生一个socket的数据结构
socket_get_option() 获取socket选项
socket_getpeername() 获取远程类似主机的ip地址
socket_getsockname() 获取本地socket的ip地址
socket_iovec_add() 添加一个新的向量到一个分散/聚合的数组
socket_iovec_alloc() 这个函数创建一个能够发送接收读写的iovec数据结构
socket_iovec_delete() 删除一个已分配的iovec
socket_iovec_fetch() 返回指定的iovec资源的数据
socket_iovec_free() 释放一个iovec资源
socket_iovec_set() 设置iovec的数据新值
socket_last_error() 获取当前socket的最后错误代码
socket_listen() 监听由指定socket的所有连接
socket_read() 读取指定长度的数据
socket_readv() 读取从分散/聚合数组过来的数据
socket_recv() 从socket里结束数据到缓存
socket_recvfrom() 接受数据从指定的socket,如果没有指定则默认当前socket
socket_recvmsg() 从iovec里接受消息
socket_select() 多路选择
socket_send() 这个函数发送数据到已连接的socket
socket_sendmsg() 发送消息到socket
socket_sendto() 发送消息到指定地址的socket
socket_set_block() 在socket里设置为块模式
socket_set_nonblock() socket里设置为非块模式
socket_set_option() 设置socket选项
socket_shutdown() 这个函数允许你关闭读、写、或指定的socket
socket_strerror() 返回指定错误号的周详错误
socket_write() 写数据到socket缓存
socket_writev() 写数据到分散/聚合数组
5. PHP Socket模拟请求
我们使用stream_socket来模拟:
/** * * @param $data= array=array('key'=>value) */ function post_contents($data = array()) { $post = $data ? http_build_query($data) : ''; $header = "POST /test/ HTTP/1.1" . "\n"; $header .= "User-Agent: Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.1;+SV1)" . "\n"; $header .= "Host: localhost" . "\n"; $header .= "Accept: */*" . "\n"; $header .= "Referer: http://localhost/test/" . "\n"; $header .= "Content-Length: ". strlen($post) . "\n"; $header .= "Content-Type: application/x-www-form-urlencoded" . "\n"; $header .= "\r\n"; $ddd = $header . $post; $fp = stream_socket_client("tcp://localhost:80", $errno, $errstr, 30); $response = ''; if (!$fp) { echo "$errstr ($errno)<br />\n"; } else { fwrite($fp, $ddd); $i = 1; while ( !feof($fp) ) { $r = fgets($fp, 1024); $response .= $r; //处理这一行 } } fclose($fp); return $response; }
注意,以上程序可能会进入死循环;
这个PHP的feof($fp) 需要注意的地方了,我们来分析为什么进入死循环。
while ( !feof($fp) ) { $r = fgets($fp, 1024); $response .= $r; }
实际上,feof是可靠的,但是结合fgets函数一块使用的时候,必须要小心了。一个常见的做法是:
$fp = fopen("myfile.txt", "r"); while (!feof($fp)) { $current_line = fgets($fp); //对结果做进一步处理,防止进入死循环 }
当处理纯文本的时候,fgets获取最后一行字符后,foef函数返回的结果并不是TRUE。实际的运算过程如下:
1) while()继续循环。
2) fgets 获取倒数第二行的字符串
3) feof返回false,进入下一次循环
4)fgets获取最后一行数据
5) 一旦fegets函数被调用,feof函数仍然返回的是false。所以继续执行循环
6) fget试图获取另外一行,但实际结果是空的。实际代码没有意识到这一点,试图处理另外根本不存在的一行,但fgets被调用了,feof放回的结果仍然是false
7) .....
8) 进入死循环

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

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

Python은 배우기 쉽고 강력한 기능을 통해 초보자에게 이상적인 프로그래밍 입문 언어입니다. 기본 사항은 다음과 같습니다. 변수: 데이터(숫자, 문자열, 목록 등)를 저장하는 데 사용됩니다. 데이터 유형: 변수의 데이터 유형(정수, 부동 소수점 등)을 정의합니다. 연산자: 수학 연산 및 비교에 사용됩니다. 제어 흐름: 코드 실행(조건문, 루프) 흐름을 제어합니다.

Python은 초보자에게 문제 해결 능력을 부여합니다. 사용자 친화적인 구문, 광범위한 라이브러리 및 변수, 조건문 및 루프 사용 효율적인 코드 개발과 같은 기능을 제공합니다. 데이터 관리에서 프로그램 흐름 제어 및 반복 작업 수행에 이르기까지 Python은 제공합니다.

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

C는 초보자가 시스템 프로그래밍을 배우기에 이상적인 선택입니다. 여기에는 헤더 파일, 기능 및 주요 기능이 포함되어 있습니다. "HelloWorld"를 인쇄할 수 있는 간단한 C 프로그램에는 표준 입출력 함수 선언이 포함된 헤더 파일이 필요하며 인쇄하려면 기본 함수에서 printf 함수를 사용합니다. C 프로그램은 GCC 컴파일러를 사용하여 컴파일하고 실행할 수 있습니다. 기본 사항을 마스터한 후에는 데이터 유형, 함수, 배열 및 파일 처리와 같은 주제로 이동하여 능숙한 C 프로그래머가 될 수 있습니다.
