You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在UWP中使用C#完整读取网络套接字的传入数据?

UWP 中 StreamSocket 完整读取请求数据的解决方案

我太懂你的困扰了——之前在.NET里能用的套接字读取方案,到UWP里处处受限,ReadTimeout不能用、同步读取容易阻塞,连Length属性都直接抛异常,确实头疼。针对你做简易REST服务器读取POST数据的场景,我给你一套UWP专属的实现方案:

核心思路

UWP的StreamSocket输入流是纯异步设计的,完全不能依赖同步读取逻辑。我们需要通过异步循环读取覆盖两种常见HTTP请求体传输场景:

  1. 带Content-Length头的常规请求
  2. 无Content-Length但用Transfer-Encoding: chunked分块编码的请求(HTTP/1.1标准)
  3. 既无长度头也不分块的旧版HTTP/1.0请求(读取到流结束)

完整实现代码

直接替换你现有的conn_received方法,用异步逻辑重构:

private async void conn_received(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
    // 用using自动释放资源,避免UWP沙箱内资源泄漏
    using (var socket = args.Socket)
    using (var inputStream = socket.InputStream)
    using (var reader = new StreamReader(inputStream.AsStreamForRead()))
    {
        // 第一步:读取请求头
        string requestLine = await reader.ReadLineAsync();
        if (string.IsNullOrEmpty(requestLine)) return;

        var headers = new Dictionary<string, string>();
        string headerLine;
        while (!string.IsNullOrEmpty(headerLine = await reader.ReadLineAsync()))
        {
            var splitPos = headerLine.IndexOf(':');
            if (splitPos > 0)
            {
                var key = headerLine.Substring(0, splitPos).Trim();
                var value = headerLine.Substring(splitPos + 1).Trim();
                headers[key] = value;
            }
        }

        // 第二步:读取请求体
        string requestBody = string.Empty;
        if (headers.TryGetValue("Transfer-Encoding", out var transferEncoding) 
            && transferEncoding.Equals("chunked", StringComparison.OrdinalIgnoreCase))
        {
            // 处理分块编码的请求体
            requestBody = await ReadChunkedBodyAsync(reader);
        }
        else if (headers.TryGetValue("Content-Length", out var lengthStr) 
            && int.TryParse(lengthStr, out int contentLength))
        {
            // 处理带Content-Length的请求体
            char[] buffer = new char[contentLength];
            int totalRead = 0;
            while (totalRead < contentLength)
            {
                int readBytes = await reader.ReadAsync(buffer, totalRead, contentLength - totalRead);
                if (readBytes == 0) break; // 提前断开,做异常处理
                totalRead += readBytes;
            }
            requestBody = new string(buffer, 0, totalRead);
        }
        else
        {
            // 读取到流结束(适用于HTTP/1.0无长度头的情况)
            var bodyBuilder = new StringBuilder();
            char[] buffer = new char[4096]; // 用4KB缓冲区平衡性能和内存
            int readBytes;
            while ((readBytes = await reader.ReadAsync(buffer, 0, buffer.Length)) > 0)
            {
                bodyBuilder.Append(buffer, 0, readBytes);
            }
            requestBody = bodyBuilder.ToString();
        }

        // 这里写你的业务逻辑,比如解析POST数据
        // ... other stuff ...
    }
}

// 处理HTTP分块编码的辅助方法
private async Task<string> ReadChunkedBodyAsync(StreamReader reader)
{
    var chunkBuilder = new StringBuilder();
    while (true)
    {
        // 读取块大小(十六进制格式)
        string chunkSizeLine = await reader.ReadLineAsync();
        if (string.IsNullOrEmpty(chunkSizeLine)) break;
        if (!int.TryParse(chunkSizeLine.Trim(), System.Globalization.NumberStyles.HexNumber, null, out int chunkSize))
            break;
        if (chunkSize == 0) break; // 分块结束标记

        // 读取当前块的内容
        char[] chunkBuffer = new char[chunkSize];
        int totalRead = 0;
        while (totalRead < chunkSize)
        {
            int readBytes = await reader.ReadAsync(chunkBuffer, totalRead, chunkSize - totalRead);
            if (readBytes == 0) break;
            totalRead += readBytes;
        }
        chunkBuilder.Append(chunkBuffer, 0, totalRead);

        // 跳过块末尾的CRLF分隔符
        await reader.ReadLineAsync();
    }
    // 跳过结束块后的CRLF
    await reader.ReadLineAsync();
    return chunkBuilder.ToString();
}

关键注意点

  • 全程异步:所有读取操作都用Async后缀的方法,彻底避免UWP线程阻塞导致的死锁或UI卡顿问题
  • 分块编码必须处理:这是HTTP/1.1中无Content-Length时的标准传输方式,直接读流会拿到带块大小标记的无效数据
  • 资源自动释放:用using包裹套接字和流对象,UWP沙箱对资源泄漏的容忍度很低,必须严格处理
  • 权限声明:别忘了在Package.appxmanifest里开启Internet(Client & Server)或Private Networks(Client & Server)权限,否则套接字根本连不上

内容的提问来源于stack exchange,提问作者andyt_3185834

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:55:12