文档:websocket部分

This commit is contained in:
若汝棋茗
2024-11-08 12:26:52 +08:00
parent 2f9de30553
commit aefe08f349

View File

@@ -32,7 +32,9 @@ title: 创建WebSocket服务器
### 4.1 简单直接创建
通过插件创建的话,只能指定一个特殊`url`路由。如果想获得连接前的`Http`请求,也必须再添加一个实现`IWebSocketPlugin`接口的插件,然后从`OnHandshaking`方法中捕获
可以使用WebSocket插件直接指定一个特殊`url`路由来完全接收WebSocket连接
然后通过插件来接收数据。(例:下列接收数据)
```csharp showLineNumbers
var service = new HttpService();
@@ -128,26 +130,28 @@ private static bool VerifyConnection(IHttpSessionClient client, HttpContext cont
### 4.3 通过WebApi创建
通过WebApi的方式会更加灵活也能很方便的获得Http相关参数。还能实现多个Url的连接路由。
实现步骤:
1. 必须配置`ConfigureRpcStore`,和注册`MyServer`
2. 必须添加`WebApiParserPlugin`
1. 配置`WebApi`相关,详情请看[WebApi](./webapi.mdx)
2. 在插件中接收`WebSocket`连接。
```csharp showLineNumbers
```csharp {8-11,15} showLineNumbers
var service = new HttpService();
await service.SetupAsync(new TouchSocketConfig()//加载配置
.SetListenIPHosts(7789)
.ConfigureContainer(a =>
{
a.AddConsoleLogger();
a.AddRpcStore(store =>
{
store.RegisterServer<MyApiServer>();//注册服务
});
})
.ConfigurePlugins(a =>
{
a.UseWebApi()
.ConfigureRpcStore(store =>
{
store.RegisterServer<MyServer>();
});
a.UseWebApi();
}));
await service.StartAsync();
@@ -155,25 +159,79 @@ await service.StartAsync();
service.Logger.Info("服务器已启动");
```
```csharp showLineNumbers
public class MyServer : RpcServer
【接收连接】
```csharp {16} showLineNumbers
public class MyApiServer : RpcServer
{
private readonly ILog m_logger;
public MyServer(ILog logger)
public MyApiServer(ILog logger)
{
this.m_logger = logger;
}
[Router("/[api]/[action]")]
[WebApi(HttpMethodType.GET)]
public void ConnectWS(IWebApiCallContext callContext)
public async Task ConnectWS(IWebApiCallContext callContext)
{
if (callContext.Caller is HttpSessionClient SessionClient)
if (callContext.Caller is HttpSessionClient sessionClient)
{
if (SessionClient.SwitchProtocolToWebSocket(callContext.HttpContext))
if (await sessionClient.SwitchProtocolToWebSocketAsync(callContext.HttpContext))
{
m_logger.Info("WS通过WebApi连接");
var webSocket = sessionClient.WebSocket;
}
}
}
}
```
或者接收到连接后,直接使用`WebSocket`接收。这样如果想直接在`WebApi`返回数据也比较方便。
```csharp {16-43} showLineNumbers
public class MyApiServer : RpcServer
{
private readonly ILog m_logger;
public MyApiServer(ILog logger)
{
this.m_logger = logger;
}
[Router("/[api]/[action]")]
[WebApi(HttpMethodType.GET)]
public async Task ConnectWS(IWebApiCallContext callContext)
{
if (callContext.Caller is HttpSessionClient sessionClient)
{
if (await sessionClient.SwitchProtocolToWebSocketAsync(callContext.HttpContext))
{
m_logger.Info("WS通过WebApi连接");
var webSocket = sessionClient.WebSocket;
webSocket.AllowAsyncRead = true;
while (true)
{
using (var tokenSource=new CancellationTokenSource(TimeSpan.FromSeconds(30)))
{
using (var receiveResult = await webSocket.ReadAsync(tokenSource.Token))
{
if (receiveResult.IsCompleted)
{
//webSocket已断开
return;
}
//webSocket数据帧
var dataFrame = receiveResult.DataFrame;
//此处可以处理数据
}
}
}
}
}
}
@@ -185,13 +243,13 @@ public class MyServer : RpcServer
使用上下文直接创建的优点在于能更加个性化的实现`WebSocket`的连接。
```csharp showLineNumbers
class MyHttpPlugin : PluginBase, IHttpPlugin<IHttpSessionClient>
class MyHttpPlugin : PluginBase, IHttpPlugin
{
public async Task OnHttpRequest(IHttpSessionClient client, HttpContextEventArgs e)
{
if (e.Context.Request.UrlEquals("/GetSwitchToWebSocket"))
{
var result =await client.SwitchProtocolToWebSocket(e.Context);
var result = await client.SwitchProtocolToWebSocketAsync(e.Context);
return;
}
await e.InvokeNext();
@@ -220,7 +278,6 @@ WebSocket服务器接收消息目前有两种方式。第一种就是通过
### 5.1 简单接收消息
【定义插件】
```csharp showLineNumbers
public class MyWebSocketPlugin : PluginBase, IWebSocketReceivedPlugin
{
@@ -309,7 +366,13 @@ await service.StartAsync();
### 5.2 WebSocket显式ReadAsync
`WebSocket`显式`ReadAsync`数据,实际上也要用到插件,但是,使用的仅仅是`IWebSocketHandshakedPlugin`,因为我们只需要拦截`握手成功`的消息
`WebSocket`显式`ReadAsync`数据,实际上是直接通过`WebSocket`直接循环读取数据
一般的,如果`WebSocket`是常规连接,则可能需要使用`IWebSocketHandshakedPlugin`插件,在`握手成功`的后直接读取数据。
如果连接是通过`WebApi`、或者`Http上下文`创建的连接,则可以直接使用`ReadAsync`。
总之要能拿到`WebSocket`对象,则可以直接使用。
和`简单接收消息`相比,使用`ReadAsync`接收消息可以直接访问代码上下文资源,这可能在处理`中继数据`时是方便的。