c#无法原生实现webrtc文件传输,需通过webview2嵌入浏览器并由js操作datachannel,c#仅负责信令、文件读写与ui;关键点包括严格json序列化、arraybuffer传输、显式设置binarytype、signalr启用websocket、应用层分块序号控制及避免内存加载大文件。

WebRTC 文件传输在 C# 中不可直接实现
浏览器里的 WebRTC 是 JS API,C# 本身没有原生 RTCPeerConnection 实现,也不能直接调用 createDataChannel。想用 C# 做“端”参与点对点文件传输,必须借助桥接层——要么把 C# 当信令服务器(纯中转),要么用 C# 驱动一个嵌入式浏览器(如 CEF / WebView2),再通过 JS 操作 WebRTC。
用 WebView2 + JS 搭建 C# 主控的 WebRTC 文件通道
这是最贴近你需求的路径:C# 窗体程序加载本地 HTML 页面,页面里用 JS 走标准 WebRTC 流程,C# 仅负责信令交换、文件读写和 UI 控制。关键点不是“C# 做 WebRTC”,而是“C# 管 WebRTC”。
常见错误现象:Failed to execute 'addIceCandidate' on 'RTCPeerConnection': Error processing ICE candidate,通常是因为 C# 发送的 SDP 或 candidate 字符串里多了换行或空格,JS 解析失败。
- 信令消息必须严格 JSON 序列化,禁用
Newtonsoft.Json的Formatting.Indented,避免换行干扰 JSJSON.parse - 从 C# 向 JS 注入文件内容时,别传完整二进制——改用
ArrayBuffer+postMessage,配合Transferable避免拷贝开销 -
dataChannel.binaryType = 'arraybuffer'必须在onopen后显式设置,否则收到的是Blob,后续arrayBuffer()会触发异步 Promise,容易漏处理
信令服务器用 ASP.NET Core 最简够用
WebRTC 不需要复杂业务逻辑,只要能广播 offer/answer/candidate 就行。ASP.NET Core 的 Hub 配合 SignalR 是最小可行方案,比自己手写 WebSocket 更稳。
性能影响:SignalR 默认用长轮询 fallback,务必在 Startup.cs 或 Program.cs 中强制启用 WebSocket:options.Transports = HttpTransportType.WebSockets,否则 candidate 推送延迟高,连接大概率失败。
容易踩的坑:Hub.OnConnectedAsync 里没存 Context.ConnectionId,导致后续广播找不到目标;或者用 Clients.All.SendAsync 替代 Clients.Client(connectionId).SendAsync,造成消息发错人。
大文件分块 + 断点续传得自己补
WebRTC DataChannel 默认不保证顺序和重传(SCTP 的 reliability 参数只控制是否启用重传,不解决丢包后重组问题),浏览器之间传 >10MB 文件大概率卡住或乱序。
必须加一层应用层协议:
- 每块数据包带
seq: number和total: number字段,JS 收到后缓存并检查是否齐备 - C# 端读文件用
FileStream.ReadAsync(buffer, offset, count)分 64KB 块,别用File.ReadAllBytes一次性加载,内存爆掉 - 别依赖
dataChannel.bufferedAmount判断发送节奏——它只反映内核缓冲区,不反映远端接收能力;应等 JS 回传ack: seq再发下一块
真正麻烦的不是连通,是让两台不同网络环境下的浏览器,在 NAT 穿透成功后,还能稳定收全几 MB 的连续 ArrayBuffer。这一步没日志、没回调、出问题只能靠 Wireshark 抓 SCTP 包——多数人卡在这儿就放弃了。










