# 多端口監聽
---
在實際運用場景中,服務器可能需要監聽不同host下的不同端口。比如,一個應用服務器,可能需要監聽外網的服務端口,同時也需要監聽內網的管理端口。在Swoole中,可以輕松的實現這樣的功能。 Swoole提供了addlistener函數用于給服務器添加一個需要監聽的host及port,并指定對應的Socket類型(TCP,UDP,Unix Socket以及對應的IPv4和IPv6版本)。 代碼如下:
```php
$serv = new swoole_server("192.168.1.1", 9501); // 監聽外網的9501端口
$serv->addlistener("127.0.0.1", 9502 , SWOOLE_TCP); // 監聽本地的9502端口
$serv->start(); // addlistener必須在start前調用
```
此時,swoole_server就會同時監聽兩個host下的兩個端口。這里要注意的是,來自兩個端口的數據會在同一個`onReceive`回調函數中獲取到,這時就要用到swoole的另一個成員函數connection_info,通過這個函數獲取到fd的from_port,就可以判定消息的類型。
```php
$info = $serv->connection_info($fd, $from_id);
//來自9502的內網管理端口
if($info['from_port'] == 9502) {
$serv->send($fd, "welcome admin\n");
}
//來自外網
else {
$serv->send($fd, 'Swoole: '.$data);
}
```
## 多端口混合協議接聽
通過上面的實例可以看到,使用上面的方法進行多端口監聽有諸多的局限性:協議單一,回調函數無法區分等。在實際應用中,我們往往希望服務能夠同時監聽兩個端口,并且兩個端口分別采用不同的協議,比如一個端口采用RPC協議提供服務,另一個端口提供Http協議用于Web管理頁面。
因此,Swoole從1.8.0版本開始提供了一套全新的多端口監聽方式。在1.8.0以后的版本,Server可以監聽多個端口,每個端口都可以設置不同的協議處理方式(set)和回調函數(on)
開始監聽新端口的代碼如下:
```php
$port1 = $server->listen("127.0.0.1", 9501, SWOOLE_SOCK_TCP);
$port2 = $server->listen("127.0.0.1", 9502, SWOOLE_SOCK_UDP);
$port3 = $server->listen("127.0.0.1", 9503, SWOOLE_SOCK_TCP | SWOOLE_SSL);
```
可以看到,新添加的監聽端口可以設置多種屬性,監聽的IP,端口號,TCP或者UDP,是否需要SSL加密。
除此之外,每個新建立的Port對象還可以分別設置配置選項,如下所示:
```php
$port1->set( // 開啟固定包頭協議
'open_length_check' => true,
'package_length_type' => 'N',
'package_length_offset' => 0,
'package_max_length' => 800000,
);
$port3->set( // 開啟EOF協議并設置SSL文件
'open_eof_split' => true,
'package_eof' => "\r\n",
'ssl_cert_file' => 'ssl.cert',
'ssl_key_file' => 'ssl.key',
);
```
除了協議不同,每個Port還可以設置自己獨有的回調函數,由此避免了在同一個回調函數里針對數據來源進行判定的問題。
```php
$port1->on('receive', function ($serv, $fd, $from_id, $data) {
$serv->send($fd, 'Swoole: '.$data);
$serv->close($fd);
});
$port3->on('receive', function ($serv, $fd, $from_id, $data) {
echo "Hello {$fd} : {$data}\n";
});
```
### 注意事項
* 未設置協議處理選項的監聽端口,默認使用無協議模式
* 未設置回調函數的監聽端口,使用$server對象的回調函數
* 監聽端口返回的對象類型為swoole_server_port
* 不同監聽端口的回調函數,仍然是相同的Worker進程空間內執行
* 主服務器是WebSocket或Http協議,新監聽的TCP端口默認會繼承主Server的協議設置。必須單獨調用`set`方法設置新的協議才會啟用新協議
- swoole簡介
- swoole功能概述
- 序章
- 開發必讀
- 1 環境搭建
- 1.1 環境搭建
- 1.2 搭建Echo服務器
- 2 初識Swoole
- 2.1 Worker進程
- 2.2 TaskWorker進程
- 2.3 Timer定時器
- 2.4 Process進程
- 2.5 Table內存表
- 2.6 多端口監聽
- 2.7 sendfile文件支持
- 2.8 SSL支持
- 2.9 熱重啟
- 2.10 http_server
- 附錄*server配置
- 附錄*server函數
- 附錄*server屬性
- 附錄*server回調函數
- 附錄*server高級特性
- 心跳檢測
- 3 Swoole協議
- 3.1 EOF協議
- 3.2 固定包頭協議
- 3.3 Http協議
- 3.4 WebSocket協議
- 3.5 MTQQ協議
- 內置http_server
- 內置websocket_server
- Swoole\Redis\Server
- 4 Swoole異步IO
- 4.1 AsyncIO
- 異步文件系統IO
- swoole_async_readfile
- swoole_async_writefile
- swoole_async_read
- swoole_async_write
- 5 swoole異步客戶端
- ws_client
- http_client
- mysql_client
- redis_client
- tcp_client
- http2_client
- 6 swoole協程
- Swoole\Coroutine\Http\Client
- Swoole\Coroutine\MySQL
- Swoole\Coroutine\Redis
- Coroutine\PostgreSQL
- Swoole\Coroutine\Client
- Swoole\Coroutine\Socket
- Swoole\Coroutine\Channel
- Coroutine
- Swoole\Coroutine::create
- Swoole\Coroutine::resume
- Swoole\Coroutine::suspend
- Swoole\Coroutine::sleep
- Coroutine::getaddrinfo
- Coroutine::gethostbyname
- swoole_async_dns_lookup_coro
- Swoole\Coroutine::getuid
- getDefer
- setDefer
- recv
- Coroutine::stats
- Coroutine::fread
- Coroutine::fget
- Coroutine::fwrite
- Coroutine::readFIle
- Coroutine::writeFIle
- Coroutine::exec
- 7 swoole_process
- process::construct
- process::start
- process::name
- process::signal
- process::setaffinity
- process::exit
- process::kill
- process::daemon
- process->exec
- process::wait
- process::alarm
- 8 swoole定時器
- swoole_timer_tick
- swoole_timer_after
- swoole_timer_clear
- 9 swoole_event
- swoole_event_add
- swoole_event_set
- swoole_event_del
- swoole_event_wait
- swoole_event_defer
- swoole_event_write
- swoole_event_exit
- swoole提供的function
- 常見問題
- 客戶端鏈接失敗原因
- 如何設置進程數
- 如何實現異步任務
- 如何選擇swoole三種模式
- php中哪些函數是阻塞的
- 是否可以共用1個redis或mysql連接
- 如何在回調函數中訪問外部的變量
- 為什么不要send完后立即close
- 不同的Server程序實例間如何通信
- MySQL的連接池、異步、斷線重連
- 在php-fpm或apache中使用swoole
- 學習Swoole需要掌握哪些基礎知識
- 在phpinfo中有在php-m中沒有
- 同步阻塞與異步非阻塞選擇
- CURL發送POST請求服務器端超時
- 附錄
- 預定義常量
- 內核參數調優
- php四種回調寫法
- 守護進程程序常用數據結構
- swoole生命周期
- swoole_server中內存管理機制
- 使用jemalloc優化swoole內存分配性能
- Reactor、Worker、Task的關系
- Manager進程
- Swoole的實現
- Reactor線程
- 安裝擴展
- swoole-worker手冊
- swoole相關開源項目
- 寫在后面的話
- 版本更新記錄
- 4.0