mirror of
https://github.com/RRQM/TouchSocket.git
synced 2025-12-19 01:46:44 +08:00
文档:websocket部分
This commit is contained in:
@@ -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`接收消息可以直接访问代码上下文资源,这可能在处理`中继数据`时是方便的。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user