C#实现http协议GET、POST请求教程

云计算

C#实现http协议GET、POST请求教程

2025-03-13 00:22


使用 DnsEndPoint自动解析DNS记录 设置5秒超时防止僵死连接 2. SSL/TLS加密通道

                                            




?️ 基础代码增强版

using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;

class HttpSocketClient : IDisposable
{
    private const int BufferSize = 4096;
    private readonly Socket _socket;
    private readonly NetworkStream _stream;
    private readonly SslStream _sslStream;
    private bool _disposed;

    public HttpSocketClient(string host, int port, bool useSsl)
    {
        // 创建TCP套接字
        _socket = new Socket(AddressFamily.InterNetwork, 
                           SocketType.Stream, 
                           ProtocolType.Tcp)
        {
            SendTimeout = 5000,
            ReceiveTimeout = 5000
        };

        // 建立连接
        var endpoint = new DnsEndPoint(host, port);
        _socket.Connect(endpoint);

        // 创建网络流
        _stream = new NetworkStream(_socket, FileAccess.ReadWrite, true);

        // SSL/TLS处理
        if (useSsl)
        {
            _sslStream = new SslStream(_stream, false, ValidateServerCertificate);
            _sslStream.AuthenticateAsClient(host);
        }
    }

    public string SendRequest(string method, string path, Dictionary<string, string> headers)
    {
        // 构造请求报文
        var request = BuildRequest(method, path, headers);
        byte[] requestBytes = Encoding.ASCII.GetBytes(request);

        // 发送请求
        ( _sslStream ?? (Stream)_stream ).Write(requestBytes);

        // 接收响应
        return ReadResponse();
    }

    private string BuildRequest(string method, string path, Dictionary<string, string> headers)
    {
        var sb = new StringBuilder();
        sb.Append($"{method} {path} HTTP/1.1\r\n");
      
        foreach (var header in headers)
        {
            sb.Append($"{header.Key}: {header.Value}\r\n");
        }
      
        sb.Append("\r\n");
        return sb.ToString();
    }

    private string ReadResponse()
    {
        // 解析响应头和正文
        using var memStream = new MemoryStream();
        var buffer = new byte[BufferSize];
        int bytesRead;

        do
        {
            bytesRead = ( _sslStream ?? (Stream)_stream ).Read(buffer, 0, BufferSize);
            memStream.Write(buffer, 0, bytesRead);
        } while (bytesRead > 0);

        return Encoding.UTF8.GetString(memStream.ToArray());
    }

    private bool ValidateServerCertificate(object sender, X509Certificate certificate,
        X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        // 实际生产环境需验证证书合法性
        return true; // 测试环境跳过验证
    }

    public void Dispose()
    {
        if (_disposed) return;
      
        _sslStream?.Dispose();
        _stream?.Dispose();
        _socket?.Dispose();
        _disposed = true;
    }
}

? 核心代码解析

1. 连接初始化

var endpoint = new DnsEndPoint(host, port);
_socket.Connect(endpoint);
  • 使用 DnsEndPoint自动解析DNS记录
  • 设置5秒超时防止僵死连接

2. SSL/TLS加密通道

_sslStream.AuthenticateAsClient(host);
  • 支持HTTPS协议加密传输
  • ValidateServerCertificate需实现证书校验逻辑

3. 请求构造器

sb.Append($"{method} {path} HTTP/1.1\r\n");
  • 严格遵循HTTP报文格式
  • 自动生成标准请求头

4. 响应接收优化

do {
    bytesRead = stream.Read(buffer, 0, BufferSize);
    memStream.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
  • 使用内存流提高读取效率
  • 4KB缓冲区平衡内存与性能

⚡️ 使用示例

using var client = new HttpSocketClient("example.com", 443, true);

var headers = new Dictionary<string, string>
{
    ["Host"] = "example.com",
    ["User-Agent"] = "CustomSocketClient/1.0",
    ["Accept"] = "text/html"
};

try 
{
    string response = client.SendRequest("GET", "/api/data", headers);
    Console.WriteLine(response);
}
catch (SocketException ex)
{
    Console.WriteLine($"网络错误: {ex.SocketErrorCode}");
}

?️ 安全增强方案

1. 证书验证(生产环境必备)

private bool ValidateServerCertificate(...)
{
    if (sslPolicyErrors != SslPolicyErrors.None)
        return false;
      
    var cert = new X509Certificate2(certificate);
    return cert.Verify();
}

2. 请求头注入防护

foreach (var header in headers)
{
    if (header.Key.Contains('\r') || header.Value.Contains('\n'))
        throw new ArgumentException("非法头信息");
}

3. 响应大小限制

const int MaxResponseSize = 10 * 1024 * 1024; // 10MB
if (memStream.Length > MaxResponseSize)
    throw new InvalidOperationException("响应超限");

? 与HttpClient对比

特性 Socket实现 HttpClient
协议控制粒度 ⭐⭐⭐⭐⭐ ⭐⭐
连接复用能力 ⭐⭐ ⭐⭐⭐⭐⭐
开发复杂度 ⭐⭐⭐⭐⭐
性能优化空间 ⭐⭐⭐⭐ ⭐⭐⭐
标准协议支持 需手动实现 自动处理

? 应用场景建议

适合使用Socket的情况
✅ 需要实现自定义传输协议
✅ 进行网络层性能调优
✅ 处理特殊网络设备通信

推荐使用HttpClient的情况
✅ 快速实现标准HTTP通信
✅ 需要连接池管理
✅ 依赖注入场景


通过本方案可深入理解HTTP协议底层机制,但实际生产环境建议优先使用 HttpClient。如需深度优化网络性能,可参考《.NET高性能网络编程》专业文献。开发完成后务必进行:
? 压力测试
? 安全审计
? 性能剖析


标签:
  • C#
  • GET
  • http
  • POST