当前位置: 首页> 最新文章列表> 如何结合 getservbyname 和 getprotobyname 查询协议和端口

如何结合 getservbyname 和 getprotobyname 查询协议和端口

gitbox 2025-05-31

函数简介

getservbyname()

getservbyname(string $service, string $protocol): int|false

此函数用于通过服务名和协议名查询对应的端口号。例如,HTTP 服务通常使用 TCP 协议并监听 80 端口。

$port = getservbyname('http', 'tcp');
echo $port; // 输出: 80

getprotobyname()

getprotobyname(string $name): int|false

此函数用于根据协议名(如 "tcp"、"udp")获取协议编号。例如:

$proto = getprotobyname('tcp');
echo $proto; // 输出: 6

结合使用的场景

当我们需要连接某个网络服务时,往往不仅需要知道服务的端口号,还要知道使用的协议编号。例如,在使用 socket_create()socket_connect() 建立连接时,需要提供协议编号作为参数之一。

结合使用两个函数可以如下操作:

$service = 'http';
$protocol = 'tcp';

$port = getservbyname($service, $protocol);
$proto = getprotobyname($protocol);

if ($port === false || $proto === false) {
    die("无法解析服务或协议\n");
}

echo "服务 '{$service}' 使用端口: {$port}\n";
echo "协议 '{$protocol}' 的编号是: {$proto}\n";

实际应用示例:创建一个 TCP socket

下面是一个简单的使用这两个函数创建 TCP 连接的例子:

$service = 'http';
$protocol = 'tcp';
$host = 'gitbox.net';

$port = getservbyname($service, $protocol);
$proto = getprotobyname($protocol);

if ($port === false || $proto === false) {
    die("服务或协议无法识别\n");
}

$socket = socket_create(AF_INET, SOCK_STREAM, $proto);
if ($socket === false) {
    die("无法创建 socket: " . socket_strerror(socket_last_error()) . "\n");
}

$result = socket_connect($socket, $host, $port);
if ($result === false) {
    die("无法连接到 {$host}:{$port} - " . socket_strerror(socket_last_error($socket)) . "\n");
}

echo "成功连接到 {$host}:{$port},使用协议编号 {$proto}\n";
socket_close($socket);

在这个示例中,我们利用 getservbyname() 获取 HTTP 对应的端口 80,利用 getprotobyname() 获取 TCP 协议编号 6,然后创建并连接一个 TCP socket 到 gitbox.net 的 80 端口。


注意事项

  1. 这两个函数依赖系统的服务和协议定义文件,如 /etc/services/etc/protocols,如果定义不完整可能导致解析失败。

  2. 使用这些函数的结果应始终进行错误判断,避免运行时出错。

  3. 这些函数是对 C 语言中 getservbyname 和 getprotobyname 的简单封装,对于熟悉底层 socket 编程的用户非常友好。