เซิร์ฟเวอร์ 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 จัดการการอ่านทีละครั้งที่สั้นกว่าและโยนข้อยกเว้นเมื่อสตรีมสิ้นสุดก่อนความยาวที่ร้องขอ หากล้มเหลว ให้ทิ้งการเชื่อมต่อที่ล้มเหลวผ่านเส้นทางการทำความสะอาดของเจ้าของ

เมื่อสำเร็จ ให้หยุดที่ขอบเขตของการตอบกลับ ไบต์หลังจากนั้นเป็นของโปรโตคอลปลายทาง การอ่านล่วงหน้าที่ใหญ่กว่าต้องเก็บไบต์ส่วนเกินไว้ ไม่ใช่ทิ้งจุดเริ่มต้นของสตรีมแอปพลิเคชัน

บทความที่เกี่ยวข้อง