Fsockopen: примеры (PHP)
fsockopen(string $hostname, int $port = -1, int &$error_code = null, string &$error_message = null, ?float $timeout = null): resource|falseОсновы функции fsockopen
Функция fsockopen в PHP используется для установки сетевого соединения через сокеты. Она позволяет работать с различными протоколами, включая TCP и UDP. Основное применение — создание низкоуровневых соединений для реализации клиентов протоколов HTTP, SMTP, FTP или собственных протоколов.
- hostname — имя хоста или IP-адрес сервера. Может быть доменным именем, IPv4 или IPv6 адресом.
- port — номер порта для подключения. Для HTTP обычно 80, для HTTPS — 443.
- error_code — переменная, в которую будет записан код ошибки при неудачном подключении.
- error_string — переменная для получения текстового описания ошибки.
- timeout — время ожидания соединения в секундах. Значение по умолчанию зависит от настроек PHP.
- flags — дополнительные флаги для управления типом соединения.
- STREAM_CLIENT_CONNECT — создание постоянного соединения.
- STREAM_CLIENT_ASYNC_CONNECT — асинхронное подключение.
- STREAM_CLIENT_PERSISTENT — создание постоянного соединения.
Примеры использования fsockopen
$fp = fsockopen("example.com", 80, $errno, $errstr, 30);
if (!$fp) {
echo "Ошибка: $errstr ($errno)";
} else {
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: example.com\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}HTTP/1.1 200 OK Date: Mon, 23 Sep 2024 12:00:00 GMT Server: Apache Content-Type: text/html; charset=UTF-8 <!doctype html> <html> <head><title>Example Domain</title></head> <body>...</body> </html>
$context = stream_context_create([
'socket' => ['tcp_nodelay' => true]
]);
$fp = stream_socket_client("tcp://example.com:80", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
if ($fp) {
echo "Соединение установлено";
fclose($fp);
}Соединение установлено
Альтернативные функции в PHP
Более современная альтернатива с поддержкой контекстов потоков. Рекомендуется для новых проектов.
Библиотека для сложных HTTP-запросов с поддержкой cookies, сессий и SSL. Предпочтительна для работы с веб-API.
Функции модуля Socket предоставляют более низкоуровневый контроль над сокетами.
Упрощенный способ получения данных по HTTP без необходимости ручного формирования запросов.
Аналоги в других языках
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("example.com", 80))
s.sendall(b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
print(s.recv(1024).decode())
s.close()const net = require('net');
const client = net.createConnection({ port: 80, host: 'example.com' }, () => {
client.write('GET / HTTP/1.1\r\nHost: example.com\r\n\r\n');
});
client.on('data', (data) => console.log(data.toString()));package main
import (
"fmt"
"net"
"io"
)
func main() {
conn, err := net.Dial("tcp", "example.com:80")
if err != nil { panic(err) }
fmt.Fprintf(conn, "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
io.Copy(os.Stdout, conn)
conn.Close()
}Распространенные ошибки
$fp = fsockopen("nonexistent-domain.xyz", 80, $errno, $errstr, 2);
if (!$fp) {
echo "Ошибка $errno: $errstr";
}Ошибка 110: Connection timed out
$fp = fsockopen("example.com", 99999, $errno, $errstr, 5);
echo $errstr;Cannot assign requested address
$fp = fsockopen("ssl://example.com", 443, $errno, $errstr, 10);
if (!$fp) echo "SSL ошибка: $errstr";SSL ошибка: Unable to enable crypto
Изменения в новых версиях PHP
Усилена строгая типизация параметров. Аргументы error_code и error_string теперь всегда передаются по ссылке.
Добавлена поддержка IPv6-адресов в стандартном формате. Улучшена обработка таймаутов.
В следующих версиях планируется улучшение поддержки асинхронных операций.
Расширенные примеры применения
$socket = fsockopen("udp://pool.ntp.org", 123, $errno, $errstr);
if ($socket) {
fwrite($socket, "\x1b".str_repeat("\0", 47));
$response = fread($socket, 48);
$unpack = unpack('N12', $response);
$timestamp = sprintf('%u', $unpack[9]) - 2208988800;
echo date('Y-m-d H:i:s', $timestamp);
fclose($socket);
}$smtp = fsockopen("tcp://smtp.example.com", 25, $errno, $errstr, 30);
if ($smtp) {
echo fgets($smtp); // Приветствие сервера
fwrite($smtp, "HELO localhost\r\n");
echo fgets($smtp); // Ответ на HELO
fwrite($smtp, "QUIT\r\n");
fclose($smtp);
}$fp = fsockopen("example.com", 80);
fwrite($fp, "HEAD / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n");
$headers = '';
while (!feof($fp) && $headers .= fgets($fp)) {
if (preg_match('/\r\n\r\n$/', $headers)) break;
}
preg_match('/Server: (.+)/', $headers, $matches);
echo $matches[1] ?? 'Неизвестный сервер';
fclose($fp);function checkPort($host, $port, $timeout = 5) {
$fp = @fsockopen($host, $port, $errno, $errstr, $timeout);
if ($fp) {
fclose($fp);
return "Порт $port открыт";
}
return "Порт $port закрыт: $errstr";
}
echo checkPort('example.com', 80);Порт 80 открыт