我有一个.net .exe,它监听web套接字。当我的发送方通过https转为WSS时,我的.exe无法对传入的请求进行解密。我的客户端接收到字节数组,但当我尝试将其解密为UTF编码时,它无法通过以下方式正确解密 Encoding.GetEncoding("ISO-8859-1");
代码。
public void ReadCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object
// and the handler socket
// from the asynchronous state object.
var state = (StateObject)ar.AsyncState;
// Read data from the client socket.
var bytesRead = _socket.EndReceive(ar);
// Below code doesn't decrypt correctly for wss
// but works correctly for ws
Utils.Encoding.GetString(state.Buffer, 0, bytesRead);
在你现有的代码中,你说的是套接字层的原始字节,直接从套接字层中的 Socket
到一个 Encoding
. 对于未加密的数据来说,这是很好的,因为数据的 字面意思是 同样的字节(虽然......只有握手的第一部分是文本;在HTTP头之后,你应该处理帧解析器,理想的情况下,所以要靠近一个 Encoding
这里有点危险,上下文。我也写了一个成功的,高吞吐量的,web-socket的服务器,直接来自于网络。Socket
层)。)
但是:当你在中间有任何字节翻译要做的时候,就不是那么简单了--这里的TLS就是如此(如果这是一个压缩翻译,你也会有同样的问题)。
很简单:需要有人来处理实际的TLS工作。如果你决心自己处理细节,那么你在这里最好的选择可能是包装。
Socket
<===> NetworkStream
<===> <===> SslStream
<===> (你的代码)
这意味着你将会对着 Stream
API,而非 Socket
API(大概是使用 AuthenticateAsServer()
当初始化服务器流时)。) 为了避免有两个代码库,你可以只使用。
Socket
<===> NetworkStream
<===> (你的代码)
对于 ws
层。然而,坦率地说,IMO最好让框架和库来担心这个问题--特别是如果你是在.NET Core上:你可以使用Kestrel来设置一个支持TLS的web-server,而你的代码基本上是公正的。
public void Configure(IApplicationBuilder app)
{
app.UseWebSockets(new WebSocketOptions()
{
// set KeepAliveInterval / ReceiveBufferSize / etc
});
app.Run(ctx =>
{
if (ctx.WebSockets.IsWebSocketRequest)
{
return RunClientAsync(ctx);
}
else { /* whatever you want to do when not WS/WSS */ }
});
}
private async Task RunClientAsync(HttpContext context)
{
var socket = await context.WebSockets.AcceptWebSocketAsync();
// TODO: all your read/write logic using the WebSocket API
}
这种方法在.NET Core 3.1上的伸缩性比在.NET Framework上的要好得多(检查我的状态页面);我目前在9个节点上(因为我刚好有9个节点可用)运行着~518,000个并发的web-socket连接,几乎是0%的CPU,每个节点5个端口(以避免短暂的端口耗尽)~每个节点每个端口11,500个连接。我们迁移了我们的自定义 Socket
-级代码来使用 WebSocket
API与.NET Core 3.1,因为这些改进意味着它 毫无意义 让我们维护自己的代码,处理web-socket协议的细微差别。