SOCKS5 serveris rašo keturis baitus atskirai, o klientas veikia tik sujungus tuos rašymus. Sujungimas gali pakeisti laiką, bet TCP vis dar nežada vieno skaitymo vienam rašymui.

Klientui reikia atsakymo analizatoriaus. Pasirinkus metodą ir atlikus bet kokią reikalingą autentifikaciją, SOCKS5 komandos atsakymas prasideda keturiais baitais: versija, rezultatas, rezervuotas baitas ir adreso tipas. Likęs ilgis priklauso nuo to adreso tipo.

.NET 7+ analizatorius, kuriam reikia sunaudoti tik sėkmingą CONNECT atsakymą, gali naudoti:

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);
}

Paskutiniai du baitai yra susietas prievadas. IPv4 reikia keturių baitų; IPv6 reikia šešiolikos; domeno adresas prieš vardą turi ilgio baitą.

Pateikite atšaukimo žetoną su numatytu derybų terminu. ReadExactlyAsync apdoroja trumpesnius pavienius skaitymus ir meta išimtį, kai srautas baigiasi anksčiau nei prašomas ilgis. Nepavykus, atmeskite nepavykusį ryšį jo savininko valymo keliu.

Sėkmės atveju sustokite ties atsakymo riba. Baituose po jos priklauso paskirties protokolui. Didesnis spekuliatyvus skaitymas turi išsaugoti perteklinius baitus, o ne išmesti programos srauto pradžią.

Susiję straipsniai