Socket clear error: примеры (PHP)

Использование socket_clear_error для обработки ошибок сокетов в PHP
Раздел: Сокеты
socket_clear_error(resource socket): void

Описание функции socket_clear_error

Назначение функции

Функция socket_clear_error предназначена для очистки кода ошибки сокета. Её основное применение — сброс состояния ошибки после обработки исключительной ситуации в работе с сетью.

Использование функции становится актуальным в ситуациях, когда необходимо повторно использовать сокет после возникновения ошибки или когда требуется точный контроль за состоянием сокета в циклических операциях.

Аргументы функции

Функция принимает один необязательный параметр:

  • socket (ресурс) — ресурс сокета, созданный с помощью socket_create. Если параметр не указан или равен null, функция очищает глобальную переменную, хранящую последний код ошибки сокета.

Возвращаемое значение — void. Функция не возвращает результат.

Простые примеры использования

Очистка ошибки конкретного сокета

В данном примере показано очищение ошибки для конкретного ресурса сокета.

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

// Попытка некорректного соединения для генерации ошибки
@socket_connect($socket, 'invalid.host', 80);

$errorCodeBefore = socket_last_error($socket);
echo "Код ошибки до очистки: $errorCodeBefore\n";

socket_clear_error($socket);

$errorCodeAfter = socket_last_error($socket);
echo "Код ошибки после очистки: $errorCodeAfter\n";

socket_close($socket);
Код ошибки до очистки: 11001
Код ошибки после очистки: 0
Очистка глобальной ошибки сокета

Пример демонстрирует очистку глобального кода ошибки сокета без указания конкретного ресурса.

// Создаем сокет и генерируем ошибку
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
@socket_connect($socket, 'nonexistent.domain', 9999);

$globalErrorBefore = socket_last_error();
echo "Глобальная ошибка до очистки: $globalErrorBefore\n";

socket_clear_error(); // Без аргумента

$globalErrorAfter = socket_last_error();
echo "Глобальная ошибка после очистки: $globalErrorAfter\n";
Глобальная ошибка до очистки: 11001
Глобальная ошибка после очистки: 0

Похожие функции в PHP

Функция возвращает код последней ошибки сокета. Может принимать ресурс сокета как аргумент. Используется совместно с socket_clear_error для диагностики.

Преобразует числовой код ошибки в текстовое описание. Часто применяется после socket_last_error для формирования читаемого сообщения об ошибке.

socket_get_option и socket_set_option

Функции для управления параметрами сокета. Позволяют настроить поведение сокета, что иногда помогает предотвратить возникновение ошибок.

Рекомендации по выбору

socket_clear_error используется именно для сброса состояния ошибки. Для получения информации об ошибке применяют socket_last_error и socket_strerror. Для предотвращения ошибок часто эффективнее настроить сокет через socket_set_option.

Аналоги в других языках программирования

Socket clear error в Python

В Python для работы с сокетами используют модуль socket. Ошибки обычно обрабатываются через исключения. Аналогом сброса состояния может быть повторная инициализация сокета.

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
    sock.connect(('invalid.host', 80))
except socket.error as e:
    print(f"Ошибка: {e}")
    # Создаем новый сокет вместо очистки ошибки
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
JavaScript (Node.js)

В Node.js сокеты являются объектами EventEmitter. Ошибки обрабатываются через событие 'error'. Явного сброса ошибки не предусмотрено.

const net = require('net');
const socket = new net.Socket();

socket.on('error', (err) => {
    console.log(`Ошибка: ${err.message}`);
    // Обычно сокет закрывают и создают заново
    socket.destroy();
});
Отличия от PHP

В отличие от PHP, где состояние ошибки хранится явно и требует очистки, в Python и JavaScript чаще применяется подход с исключениями или событиями, а проблемные сокеты пересоздаются.

Типичные ошибки

Передача несуществующего ресурса

Передача в функцию значения, которое не является ресурсом сокета, приводит к предупреждению.

$notASocket = 'test';
socket_clear_error($notASocket);
Warning: socket_clear_error() expects parameter 1 to be resource, string given
Игнорирование необходимости закрытия сокета

Очистка ошибки не устраняет проблему, если сокет находится в нерабочем состоянии. После очистки часто требуется корректное закрытие сокета.

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
@socket_connect($socket, 'wrong.address', 80);
socket_clear_error($socket);
// Попытка использовать сокет без пересоздания может привести к новым ошибкам
@socket_write($socket, "data"); // Скорее всего, не сработает
Очистка ошибки без её предварительной обработки

Распространенная ошибка — очистка кода ошибки без его анализа, что затрудняет отладку.

if (!socket_connect($socket, $address, $port)) {
    socket_clear_error($socket); // Ошибка потеряна
    // Лучше: $error = socket_last_error($socket);
    // Лучше: socket_clear_error($socket);
}

Изменения в версиях PHP

PHP 8.0

В PHP 8.0 сигнатура функции была изменена. Параметр socket стал необязательным (nullable). Ранее функция могла вызываться без аргументов, но формально параметр был обязательным.

// До PHP 8.0: socket_clear_error($socket)
// С PHP 8.0: socket_clear_error($socket) или socket_clear_error()
PHP 7.0 и ранее

В ранних версиях функция всегда требовала передачу ресурса сокета. Очистка глобальной ошибки выполнялась через socket_clear_error() с передачей null.

Расширенные примеры

Использование в циклических операциях

Пример демонстрирует обработку ошибок в цикле с многократными попытками соединения.

Пример php
function connectWithRetry($address, $port, $maxAttempts = 3) {
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    
    for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
        if (@socket_connect($socket, $address, $port)) {
            return $socket;
        }
        
        $errorCode = socket_last_error($socket);
        $errorMsg = socket_strerror($errorCode);
        echo "Попытка $attempt: $errorMsg\n";
        
        socket_clear_error($socket);
        usleep(500000); // Пауза 0.5 секунды
    }
    
    socket_close($socket);
    return false;
}
Интеграция с пользовательским обработчиком ошибок

Пример реализации логирования ошибок сокета с последующей очисткой.

Пример php
class SocketManager {
    private $log = [];
    
    public function safeSocketWrite($socket, $data) {
        $bytes = @socket_write($socket, $data);
        
        if ($bytes === false) {
            $errorCode = socket_last_error($socket);
            $this->log[] = [
                'time' => time(),
                'code' => $errorCode,
                'message' => socket_strerror($errorCode)
            ];
            socket_clear_error($socket);
        }
        
        return $bytes;
    }
}
Обработка множественных сокетов

Пример работы с несколькими сокетами и индивидуальной очисткой ошибок для каждого.

Пример php
$sockets = [];
$addresses = ['host1', 'host2', 'host3'];

foreach ($addresses as $host) {
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    if (!@socket_connect($socket, $host, 80)) {
        echo "Ошибка для $host: " . socket_strerror(socket_last_error($socket)) . "\n";
        socket_clear_error($socket);
    }
    $sockets[] = $socket;
}

// Дальнейшая работа с успешно созданными сокетами
Использование в неблокирующем режиме

При работе с неблокирующими сокетами ошибки могут возникать чаще. Их очистка становится важной частью управления соединением.

Пример php
socket_set_nonblock($socket);
$result = socket_connect($socket, $address, $port);

// В неблокирующем режиме connect может вернуть false с ошибкой EINPROGRESS
if ($result === false) {
    $err = socket_last_error($socket);
    if ($err === SOCKET_EINPROGRESS) {
        // Это ожидаемая ошибка для неблокирующего соединения
        socket_clear_error($socket);
        // Ждем готовности сокета с помощью select
    } else {
        // Другие ошибки обрабатываем как критические
    }
}

PHP socket_clear_error function comments

En
Socket clear error Clears the error on the socket or the last error code