SOCKS5 серверот запишува четири бајти одделно, а клиентот работи само откако тие записи ќе се спојат. Спојувањето може да го промени времето, но TCP сè уште не ветува едно читање по запис.

На клиентот му треба парсер на одговорот. По изборот на метод и секоја потребна автентикација, одговорот на SOCKS5 командата започнува со четири бајти: верзија, резултат, резервиран бајт и тип на адреса. Преостанатата должина зависи од тој тип на адреса.

Парсер за .NET 7+ што треба да консумира само успешен CONNECT одговор може да користи:

static async Task ReadConnectReply(Stream stream, CancellationToken ct)
{
    byte[] prefix = new byte[4];
    await stream.ReadExactlyAsync(prefix, ct);
    if (prefix[0] != 5 || prefix[2] != 0)
        throw new IOException("Invalid SOCKS5 reply");
    if (prefix[1] != 0)
        throw new IOException($"SOCKS5 request failed: {prefix[1]}");

    int remaining;
    switch (prefix[3])
    {
        case 1: remaining = 4 + 2; break;
        case 4: remaining = 16 + 2; break;
        case 3:
            byte[] length = new byte[1];
            await stream.ReadExactlyAsync(length, ct);
            remaining = length[0] + 2;
            break;
        default:
            throw new IOException("Unknown SOCKS5 address type");
    }
    await stream.ReadExactlyAsync(new byte[remaining], ct);
}

Последните два бајти се врзаниот порт. IPv4 бара четири бајти; IPv6 бара шеснаесет; адресата на домен носи бајт за должина пред името.

Обезбедете токен за откажување со предвидениот рок за преговори. ReadExactlyAsync обработува пократки поединечни читања и фрла исклучок кога текот завршува пред бараната должина. При неуспех, отфрлете ја неуспешната врска преку патеката за чистење на нејзиниот сопственик.

При успех, застанете на границата на одговорот. Бајтите по неа ѝ припаѓаат на протоколот на одредиштето. Поголемо спекулативно читање мора да ги зачува вишокот бајти наместо да го фрли почетокот на апликацискиот тек.

Поврзани статии