摘要:的部分是基于以及協(xié)議的。例如父進程向中寫入子進程從中讀取子進程向中寫入父進程從中讀取。默認使用對進程進行分配交給對應的線程進行監(jiān)聽線程收到某個進程的數(shù)據(jù)后會進行處理值得注意的是這個線程可能并不是發(fā)送請求的那個線程。
作者:施洪寶
一. 基礎知識 1.1 swooleswoole是面向生產(chǎn)環(huán)境的php異步網(wǎng)絡通信引擎, php開發(fā)人員可以利用swoole開發(fā)出高性能的server服務。swoole的server部分, 內(nèi)容很多, 也涉及很多的知識點, 本文僅對其server進行簡單的概述, 具體的實現(xiàn)細節(jié)在后續(xù)的文章中再進行詳細介紹。
1.2 網(wǎng)絡編程網(wǎng)絡通信是指在一臺(或者多臺)機器上啟動一個(或者多個)進程, 監(jiān)聽一個(或者多個)端口, 按照某種協(xié)議(可以是標準協(xié)議http, dns; 也可以是自行定義的協(xié)議)與客戶端交換信息。
目前的網(wǎng)絡編程多是在tcp, udp或者更上層的協(xié)議之上進行編程。swoole的server部分是基于tcp以及udp協(xié)議的。
利用udp進行編程較為簡單, 本文主要介紹tcp協(xié)議之上的網(wǎng)絡編程
TCP網(wǎng)絡編程主要涉及4種事件,
連接建立: 主要是指客戶端發(fā)起連接(connect)以及服務端接受連接(accept)
消息到達: 服務端接受到客戶端發(fā)送的數(shù)據(jù), 該事件是TCP網(wǎng)絡編程最重要的事件, 服務端對于該類事件進行處理時, 可以采用阻塞式或者非阻塞式, 除此之外, 服務端還需要考慮分包, 應用層緩沖區(qū)等問題
消息發(fā)送成功: 發(fā)送成功是指應用層將數(shù)據(jù)成功發(fā)送到內(nèi)核的套接字發(fā)送緩沖區(qū)中, 并不是指客戶端成功接受數(shù)據(jù)。對于低流量的服務而言, 數(shù)據(jù)通常一次性即可發(fā)送完, 并不需要關心此類事件。如果一次性不能將全部數(shù)據(jù)發(fā)送到內(nèi)核緩沖區(qū), 則需要關心消息是否成功發(fā)送(阻塞式編程在系統(tǒng)調(diào)用(write, writev, send等)返回后即是發(fā)送成功, 非阻塞式編程則需要考慮實際寫入的數(shù)據(jù)是否與預期一致)
連接斷開: 需要考慮客戶端斷開連接(read返回0)以及服務端斷開連接(close, shutdown)
1.3 進程間通信進程之間的通信有無名管道(pipe), 有名管道(fifo), 信號, 信號量, 套接字, 共享內(nèi)存等方式
swoole中采用unix域套接字用于多進程之間的通信(指swoole內(nèi)部進程之間)
1.4 socketpairsocketpair用于創(chuàng)建一個套接字對, 類似于pipe, 不同的是pipe是單向通信, 雙向通信需要創(chuàng)建兩次, socketpair調(diào)用一次即可實現(xiàn)雙向通信, 除此之外, 由于使用的是套接字, 還可以定義數(shù)據(jù)交換的方式
socketpair系統(tǒng)調(diào)用
int socketpair(int domain, int type, int protocol, int sv[2]); //domain表示協(xié)議簇 //type表示類型 //protocol表示協(xié)議, SOCK_STREAM表示流協(xié)議(類似tcp), SOCK_DGRAM表示數(shù)據(jù)報協(xié)議(類似udp) //sv用于存儲建立的套接字對, 也就是兩個套接字文件描述符 //成功返回0, 否則返回-1, 可以從errno獲取錯誤信息
調(diào)用成功后sv[0], sv[1]分別存儲一個文件描述符
向sv[0]中寫入, 可以從sv[1]中讀取
向sv[1]中寫入, 可以從sv[0]中讀取
進程調(diào)用socketpair后, fork子進程, 子進程會默認繼承sv[0], sv[1]這兩個文件描述符, 進而可以實現(xiàn)父子進程間通信。例如, 父進程向sv[0]中寫入, 子進程從sv[1]中讀取; 子進程向sv[1]中寫入, 父進程從sv[0]中讀取。
1.5 守護進程(daemon)守護進程是一種特殊的后臺進程, 它脫離于終端, 用于周期性的執(zhí)行某種任務
進程組
每個進程都屬于一個進程組
每個進程組都有一個進程組號, 也就是該組組長的進程號(PID)
一個進程只能為自己或者其子進程設置進程組號
會話
一個會話可以包含多個進程組, 這些進程組中最多只能有一個前臺進程組(也可以沒有)
setsid可以創(chuàng)建一個新的會話, 該進程不能是進程組的組長。setsid調(diào)用完成后, 該進程成為這個會話的首進程(領頭進程), 同時變成一個新的進程組的組長, 如果該進程之前有控制終端, 則該進程與終端的聯(lián)系被斷開
用戶通過終端登錄或者網(wǎng)絡登錄, 會創(chuàng)建一個新的會話
一個會話最多只能有一個控制終端
創(chuàng)建守護進程的方式
fork子進程后, 父進程退出, 子進程執(zhí)行setsid即可成為守護進程。這種方式下, 子進程是會話的領頭進程, 可以重新打開終端, 此時可以再次fork, fork產(chǎn)生的子進程無法再打開終端。第二次fork并不是必須的, 只是為了防止子進程再次打開終端
linux提供了daemon函數(shù)用于創(chuàng)建守護進程
1.6 swoole tcp server示例set(array( "reactor_num" => 2, //reactor thread num "worker_num" => 3, //worker process num )); //設置事件回調(diào) $serv->on("connect", function ($serv, $fd){ echo "Client:Connect. "; }); $serv->on("receive", function ($serv, $fd, $reactor_id, $data) { $serv->send($fd, "Swoole: ".$data); $serv->close($fd); }); $serv->on("close", function ($serv, $fd) { echo "Client: Close. "; }); //啟動server $serv->start();
上述代碼在cli模式下執(zhí)行時, 經(jīng)過詞法分析, 語法分析生成opcode, 進而交由zend虛擬機執(zhí)行
zend虛擬機在執(zhí)行到$serv->start()時, 啟動swoole server
上述代碼中設置的事件回調(diào)是在worker進程中執(zhí)行, 后文會詳細介紹swoole server模型
二. swoole server 2.1 base模式說明
base模式采用多進程模型, 這種模型與nginx一致, 每個進程只有一個線程, 主進程負責管理工作進程, 工作進程負責監(jiān)聽端口, 接受連接, 處理請求以及關閉連接
多個進程同時監(jiān)聽端口, 會有驚群問題, 目前swoole并沒有解決
linux 內(nèi)核3.9及其后續(xù)版本提供了新的套接字參數(shù)SO_REUSEPORT, 該參數(shù)允許多個進程綁定到同一個端口, 內(nèi)核在接受到新的連接請求時, 會喚醒其中一個進行處理, 內(nèi)核層面也會做負載均衡, 可以解決上述的驚群問題
base模式下, reactor_number參數(shù)并沒有作用, 因為每個進程只有一個線程
如果worker進程數(shù)設置為1, 則不會fork出worker進程, 主進程直接處理請求
啟動過程
php代碼執(zhí)行到$serv->start()時, 主進程進入int swServer_start(swServer *serv)函數(shù), 該函數(shù)負責啟動server
在函數(shù)swServer_start中會調(diào)用swReactorProcess_start, 這個函數(shù)會fork出多個worker進程
主進程和worker進程各自進入自己的事件循環(huán), 處理各類事件
2.2 process模式說明
這種模式為多進程多線程, 有主進程, manager進程, worker進程, task_worker進程
主進程下有多個線程, 主線程負責接受連接, 之后交給react線程處理請求。 react線程負責接收數(shù)據(jù)包, 并將數(shù)據(jù)轉(zhuǎn)發(fā)給worker進程進行處理, 之后處理worker進程返回的數(shù)據(jù)
manager進程, 該進程為單線程, 主要負責管理worker進程, 類似于nginx中的主進程, 當worker進程異常退出時, manager進程負責重新fork出一個worker進程
worker進程, 該進程為單線程, 負責具體處理請求
task_worker進程, 用于處理比較耗時的任務, 默認不開啟
worker進程與主進程中的react線程使用域套接字進行通信, worker進程之間不進行通信
啟動過程
swoole server啟動入口: swServer_start函數(shù),
//php 代碼中$serv->start(); 會調(diào)用函數(shù), 進行server start int swServer_start(swServer *serv); // 該函數(shù)首先進行必要的參數(shù)檢查 static int swServer_start_check(swServer *serv); // 其中有, if (serv->worker_num < serv->reactor_num) { serv->reactor_num = serv->worker_num; }//也就是說reactor_num <= worker_num //之后執(zhí)行factory start, 也就是swFactoryProcess_start函數(shù), 該函數(shù)會fork出manager進程, manager進程進而fork出worker進程以及task_worker進程 if (factory->start(factory) < 0) { return SW_ERR; } //然后主進程的主線程生成reactor線程 if (serv->factory_mode == SW_MODE_BASE) { ret = swReactorProcess_start(serv); } else { ret = swReactorThread_start(serv); }
如果設置了daemon模式, 在必要的參數(shù)檢查完后, 先將自己變?yōu)槭刈o進程再fork manager進程, 進而創(chuàng)建reactor線程
主進程先fork出manager進程, manager進程負責fork出worker進程以及task_worker進程。worker進程之后進入int swWorker_loop(swServer *serv, int worker_id), 也就是進入自己的事件循環(huán), task_worker也是一樣, 進入自己的事件循環(huán)。
static int swFactoryProcess_start(swFactory *factory); //swFactoryProcess_start會調(diào)用swManager_start生成manager進程 int swManager_start(swServer *serv); // manager進程會fork出worker進程以及task_worker進程
主進程pthread_create出react線程, 主線程和react線程各自進入自己的事件循環(huán), reactor線程執(zhí)行static int swReactorThread_loop(swThreadParam *param), 等待處理事件
//主線程執(zhí)行swReactorThread_start, 創(chuàng)建出reactor線程 int swReactorThread_start(swServer *serv);
結(jié)構(gòu)圖
swoole process模式結(jié)構(gòu)如下圖所示,
上圖并沒有考慮task_worker進程, 在默認情況下, task_worker進程數(shù)為0
三. 請求處理流程(process模式) 3.1 reactor線程與worker進程之間的通信swoole master進程與worker進程之間的通信如下圖所示,
swoole使用SOCK_DGRAM, 而不是SOCK_STREAM, 這里是因為每個reactor線程負責處理多個請求, reactor接收到請求后會將信息轉(zhuǎn)發(fā)給worker進程, 由worker進程負責處理,如果使用SOCK_STREAM, worker進程無法對tcp進行分包, 進而處理請求
swFactoryProcess_start函數(shù)中會根據(jù)worker進程數(shù)創(chuàng)建對應個數(shù)的套接字對, 用于reactor線程與worker進程通信(swPipeUnsock_create函數(shù))
假設reactor線程有2個, worker進程有3個, 則reactor與worker之間的通信如下圖所示,
每個reactor線程負責監(jiān)聽幾個worker進程, 每個worker進程只有一個reactor線程監(jiān)聽(reactor_num<=worker_num)。swoole默認使用worker_process_id % reactor_num對worker進程進行分配, 交給對應的reactor線程進行監(jiān)聽
reactor線程收到某個worker進程的數(shù)據(jù)后會進行處理, 值得注意的是, 這個reactor線程可能并不是發(fā)送請求的那個reactor線程。
reactor線程與worker進程通信的數(shù)據(jù)包
//包頭 typedef struct _swDataHead { int fd; uint32_t len; int16_t from_id; uint8_t type; uint8_t flags; uint16_t from_fd; #ifdef SW_BUFFER_RECV_TIME double time; #endif } swDataHead; //reactor線程向worker進程發(fā)送的數(shù)據(jù), 也就是worker進程收到的數(shù)據(jù)包 typedef struct { swDataHead info; char data[SW_IPC_BUFFER_SIZE]; } swEventData; //worker進程向reactor線程發(fā)送的數(shù)據(jù), 也就是reactor線程收到的數(shù)據(jù)包 typedef struct { swDataHead info; char data[0]; } swPipeBuffer;3.2 請求處理
master進程中的主線程負責監(jiān)聽端口(listen), 接受連接(accept, 產(chǎn)生一個fd), 接受連接后將請求分配給reactor線程, 默認通過fd % reactor_num進行分配, 之后通過epoll_ctl將fd加入到對應reactor線程中(如果對應的reactor線程正在執(zhí)行epoll_wait, 主線程會阻塞), 剛加入時監(jiān)聽寫事件, 如果直接監(jiān)聽讀事件, 可能會立刻被觸發(fā), 而監(jiān)聽寫事件可以允許reactor線程進行一些初始化操作
//主線程執(zhí)行epoll_ctl將fd(新接受的連接)加入到reactor線程的監(jiān)聽隊列中 epoll_ctl(epfd, fd, ...); //對應的reactor線程如果正在執(zhí)行 epoll_wait(epfd, ...);
這種情況主線程會被阻塞(兩個線程同時操作epfd)
如果reactor線程沒有正在執(zhí)行epoll_wait, 主線程則不會被阻塞, 執(zhí)行成功后直接返回
reactor線程中fd的寫事件被觸發(fā), reactor線程負責處理, 發(fā)現(xiàn)是首次加入, 沒有數(shù)據(jù)可寫, 則開啟讀事件監(jiān)聽
reactor線程讀取到用戶的請求數(shù)據(jù), 一個請求的數(shù)據(jù)接收完后, 將數(shù)據(jù)轉(zhuǎn)發(fā)給worker進程, 默認是通過fd % worker_num進行分配
reactor發(fā)送給worker進程的數(shù)據(jù)包, 會包含一個頭部, 頭部中記錄了reactor的信息
如果發(fā)送的數(shù)據(jù)過大, 則需要將數(shù)據(jù)進行分片, 限于篇幅, reactor的分片, 后續(xù)再進行詳細講述
可能存在多個reactor線程同時向同一個worker進程發(fā)送數(shù)據(jù)的情況, 故而swoole采用SOCK_DGRAM模式與worker進程進行通信, 通過每個數(shù)據(jù)包的包頭, worker進程可以區(qū)分出是由哪個reactor線程發(fā)送的數(shù)據(jù)
worker進程收到reactor發(fā)送的數(shù)據(jù)包后, 進行處理, 處理完成后, 將數(shù)據(jù)發(fā)送給主進程
worker進程發(fā)送給主進程的數(shù)據(jù)包, 也會包含一個頭部, 當reactor線程收到數(shù)據(jù)包后, 能夠知道對應的reactor線程, 請求的fd等信息
主進程收到worker進程發(fā)送的數(shù)據(jù)包, 這個會觸發(fā)某個reactor線程進行處理
這個reactor線程并不一定是之前發(fā)送請求給worker進程的那個reactor線程
主進程的每個reactor線程都負責監(jiān)聽worker進程發(fā)送的數(shù)據(jù)包, 每個worker發(fā)送的數(shù)據(jù)包只會由一個reactor線程進行監(jiān)聽, 故而只會觸發(fā)一個reactor線程
reactor線程處理worker進程發(fā)送的數(shù)據(jù)包, 如果是直接發(fā)送數(shù)據(jù)給客戶端, 則可以直接發(fā)送, 如果需要改變這個這個連接的監(jiān)聽狀態(tài)(例如close), 則需要先找到監(jiān)聽這個連接的reactor, 進而改變這個連接的監(jiān)聽狀態(tài)
reactor處理線程與reactor監(jiān)聽線程可能并不是同一個線程
reactor監(jiān)聽線程負責監(jiān)聽客戶端發(fā)送的數(shù)據(jù), 進而轉(zhuǎn)發(fā)給worker進程
reactor處理線程負責監(jiān)聽worker進程發(fā)送給主進程的數(shù)據(jù), 進而將數(shù)據(jù)發(fā)送給客戶端
四. gdb調(diào)試 4.1 process模式啟動//fork manager進程 #0 0x00007ffff67dae64 in fork () from /lib64/libc.so.6 #1 0x00007ffff553888a in swoole_fork () at /root/code/swoole-src/src/core/base.c:186 #2 0x00007ffff556afb8 in swManager_start (serv=serv@entry=0x1353f60) at /root/code/swoole-src/src/server/manager.cc:164 #3 0x00007ffff5571dde in swFactoryProcess_start (factory=0x1353ff8) at /root/code/swoole-src/src/server/process.c:198 #4 0x00007ffff556ef8b in swServer_start (serv=0x1353f60) at /root/code/swoole-src/src/server/master.cc:651 #5 0x00007ffff55dc808 in zim_swoole_server_start (execute_data=4.2 base模式啟動, return_value=0x7fffffffac50) at /root/code/swoole-src/swoole_server.cc:2946 #6 0x00000000007bb068 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /root/php-7.3.3/Zend/zend_vm_execute.h:980 #7 execute_ex (ex=0x7ffff7f850a8) at /root/php-7.3.3/Zend/zend_vm_execute.h:55485 #8 0x00000000007bbf58 in zend_execute (op_array=op_array@entry=0x7ffff5e7b340, return_value=return_value@entry=0x7ffff5e1d030) at /root/php-7.3.3/Zend/zend_vm_execute.h:60881 #9 0x0000000000737554 in zend_execute_scripts (type=type@entry=8, retval=0x7ffff5e1d030, retval@entry=0x0, file_count=file_count@entry=3) at /root/php-7.3.3/Zend/zend.c:1568 #10 0x00000000006db4d0 in php_execute_script (primary_file=primary_file@entry=0x7fffffffd050) at /root/php-7.3.3/main/main.c:2630 #11 0x00000000007be2f5 in do_cli (argc=2, argv=0x1165cd0) at /root/php-7.3.3/sapi/cli/php_cli.c:997 #12 0x000000000043fc1f in main (argc=2, argv=0x1165cd0) at /root/php-7.3.3/sapi/cli/php_cli.c:1389 // pthread_create reactor線程 #0 0x00007ffff552e960 in pthread_create@plt () from /usr/local/lib/php/extensions/no-debug-non-zts-20180731/swoole.so #1 0x00007ffff5576959 in swReactorThread_start (serv=0x1353f60) at /root/code/swoole-src/src/server/reactor_thread.c:883 #2 0x00007ffff556f006 in swServer_start (serv=0x1353f60) at /root/code/swoole-src/src/server/master.cc:670 #3 0x00007ffff55dc808 in zim_swoole_server_start (execute_data= , return_value=0x7fffffffac50) at /root/code/swoole-src/swoole_server.cc:2946 #4 0x00000000007bb068 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /root/php-7.3.3/Zend/zend_vm_execute.h:980 #5 execute_ex (ex=0x7fffffffab10) at /root/php-7.3.3/Zend/zend_vm_execute.h:55485 #6 0x00000000007bbf58 in zend_execute (op_array=op_array@entry=0x7ffff5e7b340, return_value=return_value@entry=0x7ffff5e1d030) at /root/php-7.3.3/Zend/zend_vm_execute.h:60881 #7 0x0000000000737554 in zend_execute_scripts (type=type@entry=8, retval=0x7ffff5e1d030, retval@entry=0x0, file_count=file_count@entry=3) at /root/php-7.3.3/Zend/zend.c:1568 #8 0x00000000006db4d0 in php_execute_script (primary_file=primary_file@entry=0x7fffffffd050) at /root/php-7.3.3/main/main.c:2630 #9 0x00000000007be2f5 in do_cli (argc=2, argv=0x1165cd0) at /root/php-7.3.3/sapi/cli/php_cli.c:997 #10 0x000000000043fc1f in main (argc=2, argv=0x1165cd0) at /root/php-7.3.3/sapi/cli/php_cli.c:1389
//base 模式下的啟動 #0 0x00007ffff67dae64 in fork () from /lib64/libc.so.6 #1 0x00007ffff553888a in swoole_fork () at /root/code/swoole-src/src/core/base.c:186 #2 0x00007ffff5558557 in swProcessPool_spawn (pool=pool@entry=0x7ffff2d2a308, worker=0x7ffff2d2a778) at /root/code/swoole-src/src/network/process_pool.c:392 #3 0x00007ffff5558710 in swProcessPool_start (pool=0x7ffff2d2a308) at /root/code/swoole-src/src/network/process_pool.c:227 #4 0x00007ffff55741cf in swReactorProcess_start (serv=0x1353f60) at /root/code/swoole-src/src/server/reactor_process.cc:176 #5 0x00007ffff556f21d in swServer_start (serv=0x1353f60) at /root/code/swoole-src/src/server/master.cc:666 #6 0x00007ffff55dc808 in zim_swoole_server_start (execute_data=五. 參考, return_value=0x7fffffffac50) at /root/code/swoole-src/swoole_server.cc:2946 #7 0x00000000007bb068 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /root/php-7.3.3/Zend/zend_vm_execute.h:980 #8 execute_ex (ex=0x7ffff2d2a308) at /root/php-7.3.3/Zend/zend_vm_execute.h:55485 #9 0x00000000007bbf58 in zend_execute (op_array=op_array@entry=0x7ffff5e7b340, return_value=return_value@entry=0x7ffff5e1d030) at /root/php-7.3.3/Zend/zend_vm_execute.h:60881 #10 0x0000000000737554 in zend_execute_scripts (type=type@entry=8, retval=0x7ffff5e1d030, retval@entry=0x0, file_count=file_count@entry=3) at /root/php-7.3.3/Zend/zend.c:1568 #11 0x00000000006db4d0 in php_execute_script (primary_file=primary_file@entry=0x7fffffffd050) at /root/php-7.3.3/main/main.c:2630 #12 0x00000000007be2f5 in do_cli (argc=2, argv=0x1165cd0) at /root/php-7.3.3/sapi/cli/php_cli.c:997 #13 0x000000000043fc1f in main (argc=2, argv=0x1165cd0) at /root/php-7.3.3/sapi/cli/php_cli.c:1389
UNIX網(wǎng)絡編程
UNIX環(huán)境高級編程
https://wiki.swoole.com/
https://www.cnblogs.com/welhz...
https://www.cnblogs.com/JohnA...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/31602.html
摘要:若參數(shù)和字符串相等則返回。大于則返回大于的值,小于則返回小于的值。下面的中是增加一個這里我們顯然設置了主機和端口暫且跳過在這里我們看到調(diào)用了中的方法并且將初始化好的等傳了進去,我們追進去線程數(shù) 創(chuàng)建一個server 今天我們來研究一下swoole中server相關的源碼(版本是4.3.1),首先我們先從一段簡單代碼開始 $http = new SwooleHttpServer(127....
摘要:和服務關系最密切的進程是中的進程組,絕大部分業(yè)務處理都在該進程中進行。隨后觸發(fā)一個事件各組件通過該事件進行配置文件加載路由注冊。事件每個請求到來時僅僅會觸發(fā)事件。服務器生命周期和服務基本一致,詳情參考源碼剖析功能實現(xiàn) 作者:bromine鏈接:https://www.jianshu.com/p/4c0...來源:簡書著作權(quán)歸作者所有,本文已獲得作者授權(quán)轉(zhuǎn)載,并對原文進行了重新的排版。S...
摘要:此時的協(xié)程實現(xiàn)無法完美的支持語法,其根本原因在于沒有保存棧信息。這是因為調(diào)用函數(shù)時,底層指令已經(jīng)將入棧了。協(xié)程創(chuàng)建時,底層通過函數(shù)實現(xiàn)了棧的創(chuàng)建創(chuàng)建并初始化棧為結(jié)構(gòu)分配空間創(chuàng)建新的執(zhí)行數(shù)據(jù)結(jié)構(gòu)從代碼中可以看到結(jié)構(gòu)是直接存儲在棧的底部。 作者:李樂??本文基于Swoole-4.3.2和PHP-7.1.0版本 Swoole協(xié)程簡介 ??Swoole4為PHP語言提供了強大的CSP協(xié)程編程模...
摘要:在中的應用官網(wǎng)源碼解讀號外號外歡迎大家我們開發(fā)組定了一個就線下聚一次的小目標上一篇源碼解讀反響還不錯不少同學推薦再加一篇講解一下中使用到的功能幫助大家開啟的實戰(zhàn)之旅服務器開發(fā)涉及到的相關技術(shù)領域的知識非常多不日積月累打好基礎是很難真正 date: 2017-12-14 21:34:51title: swoole 在 swoft 中的應用 swoft 官網(wǎng): https://www.sw...
摘要:服務重點基本概述協(xié)議是基于的一種新的網(wǎng)絡協(xié)議。被調(diào)用者通過狀態(tài)通知機制等來通知調(diào)用者,或通過回調(diào)函數(shù)來處理結(jié)果阻塞和非阻塞關注的是調(diào)用者等待被調(diào)用者返回調(diào)用結(jié)果時的狀態(tài)。 一、PHP7源碼安裝和Swoole源碼編譯安裝 1.1 PHP7源碼安裝 1.1.1 獲取源碼與安裝 ????獲取PHP7源碼:www.php.net tar -xzvf ... # 解壓命令 ./configur...
閱讀 2993·2021-11-04 16:06
閱讀 832·2021-09-30 09:56
閱讀 1886·2021-09-22 10:02
閱讀 2668·2019-08-29 13:43
閱讀 2282·2019-08-29 13:42
閱讀 2357·2019-08-29 12:21
閱讀 1116·2019-08-29 11:29
閱讀 1435·2019-08-26 13:51