...
 
Commits (9)
    https://gitcode.net/qq_40374647/RRQMSocket/-/commit/b8c779166cd9faf038c1ed17e4b9a77b49bdc0dd 修复示例demo 2023-05-29T19:57:32+08:00 若汝棋茗 505554090@qq.com https://gitcode.net/qq_40374647/RRQMSocket/-/commit/46459aceaa18e35acc4b5ecd21e01f34d69ac02b 更新demo 2023-05-31T13:08:58+08:00 若汝棋茗 505554090@qq.com https://gitcode.net/qq_40374647/RRQMSocket/-/commit/5066469901ec6a3720fb4b7cc1f5cc7038e9d676 添加cookie示例 2023-06-21T10:01:55+08:00 若汝棋茗 505554090@qq.com https://gitcode.net/qq_40374647/RRQMSocket/-/commit/fba8ba0a9e149e08ce3be008572a5770879ac8bd 更新tcp服务器的创建 2023-06-23T23:42:35+08:00 若汝棋茗 505554090@qq.com https://gitcode.net/qq_40374647/RRQMSocket/-/commit/543bdc0337a431832b270e2d1f4a2f3249f9be8f 增加动态添加、移除监听配置 文档 2023-06-23T23:59:03+08:00 若汝棋茗 505554090@qq.com https://gitcode.net/qq_40374647/RRQMSocket/-/commit/60a762165aeb2c80493f909f51db6c8da2a23b33 更新waitingclient 2023-06-24T22:24:45+08:00 若汝棋茗 505554090@qq.com https://gitcode.net/qq_40374647/RRQMSocket/-/commit/d070bc4acc7512c176163a369f2e2b4c467f9857 更新resetid文档 2023-06-24T22:30:31+08:00 若汝棋茗 505554090@qq.com https://gitcode.net/qq_40374647/RRQMSocket/-/commit/b985b31891e52e0b689683873ef44d1a685d7e00 更新文档 2023-06-24T23:59:25+08:00 若汝棋茗 505554090@qq.com https://gitcode.net/qq_40374647/RRQMSocket/-/commit/5e8cc4e4bcde35d3b93dc9a6bd09c71e14ee9a6f 更新demo 2023-07-04T16:33:39+08:00 若汝棋茗 505554090@qq.com
...@@ -27,7 +27,6 @@ namespace TouchRpcClientApp ...@@ -27,7 +27,6 @@ namespace TouchRpcClientApp
//后续参数为调用参数。 //后续参数为调用参数。
bool result = client.Invoke<bool>("touchrpcserverapp.myrpcserver.login", InvokeOption.WaitInvoke, textBox1.Text, textBox2.Text); bool result = client.Invoke<bool>("touchrpcserverapp.myrpcserver.login", InvokeOption.WaitInvoke, textBox1.Text, textBox2.Text);
MessageBox.Show(result.ToString()); MessageBox.Show(result.ToString());
client.SafeDispose();//client是长连接,可以复用,但在此处使用短连接。 client.SafeDispose();//client是长连接,可以复用,但在此处使用短连接。
} }
......
...@@ -10,11 +10,11 @@ namespace RpcClassLibrary.ServerInterface ...@@ -10,11 +10,11 @@ namespace RpcClassLibrary.ServerInterface
/// <summary> /// <summary>
/// 定义服务接口。 /// 定义服务接口。
/// </summary> /// </summary>
[GeneratorRpcProxy(Prefix = "RpcClassLibrary",MethodFlags = MethodFlags.IncludeCallContext)] [GeneratorRpcProxy(MethodFlags = MethodFlags.IncludeCallContext)]
public interface IUserServer:IRpcServer public interface IUserServer : IRpcServer
{ {
[GeneratorRpcMethod] [GeneratorRpcMethod]
[TouchRpc] [TouchRpc(MethodFlags = MethodFlags.IncludeCallContext)]
LoginResponse Login(ICallContext callContext,LoginRequest request); LoginResponse Login(ICallContext callContext, LoginRequest request);
} }
} }
...@@ -167,5 +167,11 @@ namespace WSClientApp ...@@ -167,5 +167,11 @@ namespace WSClientApp
break; break;
} }
} }
protected override void OnHandshaking(WebSocketClient client, HttpContextEventArgs e)
{
e.Context.Request.Headers["cookie"] = "";
base.OnHandshaking(client, e);
}
} }
} }
\ No newline at end of file
...@@ -54,6 +54,13 @@ namespace WebSocketConsoleApp ...@@ -54,6 +54,13 @@ namespace WebSocketConsoleApp
case WSDataType.Text: case WSDataType.Text:
Console.WriteLine(e.DataFrame.ToText()); Console.WriteLine(e.DataFrame.ToText());
((HttpSocketClient)client).SendWithWS(e.DataFrame.ToText()); ((HttpSocketClient)client).SendWithWS(e.DataFrame.ToText());
//using (ByteBlock byteBlock=new ByteBlock(1024*64))//估算一下你的数据大小
//{
// WSDataFrame dataFrame = new WSDataFrame();
// dataFrame.BuildResponse(byteBlock);
// ((HttpSocketClient)client).SendWithWS(byteBlock);
//}
break; break;
case WSDataType.Binary: case WSDataType.Binary:
......
...@@ -3,6 +3,7 @@ id: createtcpclient ...@@ -3,6 +3,7 @@ id: createtcpclient
title: 创建TcpClient title: 创建TcpClient
--- ---
import Tag from "@site/src/components/Tag.js";
## 一、说明 ## 一、说明
...@@ -41,56 +42,14 @@ TcpClient是Tcp系客户端基类,他直接参与tcp的连接、发送、接 ...@@ -41,56 +42,14 @@ TcpClient是Tcp系客户端基类,他直接参与tcp的连接、发送、接
数据包最大值(单位:byte),默认1024×1024×10。该值会在适当时间,直接作用DataHandlingAdapter.MaxPackageSize。 数据包最大值(单位:byte),默认1024×1024×10。该值会在适当时间,直接作用DataHandlingAdapter.MaxPackageSize。
#### SetThreadCount
多线程数量。该值在Auto模式下指示线程池的最少线程数量和IO线程数量。
设置建议:
1. 异步处理接收数据,此时线程数量设置为内核线程左右的值即可。
2. 同步处理接收数据,此时应当考虑两个因素。该操作是否为耗时操作,如果是,则该值在允许范围内,应当设置更可能大的值。如果不是,则设置为内核线程左右的值即可。
#### SetGetDefaultNewID
配置初始ID的分配策略
#### SetListenIPHosts
监听IP和端口号组,可以一次性设置多个地址。
#### SetServerName
服务器标识名称,无实际使用意义。
#### SetBacklogProperty
Tcp半连接挂起连接队列的最大长度。默认为30
#### SetMaxCount
最大可连接数,默认为10000
#### SetReceiveType #### SetReceiveType
接收类型。 接收类型。
- AUTO:自动接收模式。 - AUTO:自动接收模式。
- None:不投递IO接收申请,用户可通过GetStream,获取到流以后,自己处理接收。注意:连接端不会感知主动断开。 - None:不投递IO接收申请,用户可通过GetStream,获取到流以后,自己处理接收。注意:连接端不会感知主动断开。
#### UsePlugin
是否启用插件。在启用时或许会带来一点点性能损耗,基本上不是千万数据交互根本不值一提。
#### SetServiceSslOption #### SetServiceSslOption
Ssl配置,为Null时则不启用。 Ssl配置,为Null时则不启用。
#### UseNoDelay
设置Socket的NoDelay属性,默认false。
#### UseDelaySender
使用延迟发送。众所周知,tcp数据报文为了发送效率,会默认启用**延迟算法**。但是这种设置,只能一定程度的缓解小数据发送效率低的问题,因为它为了保证多线程发送的有序性,在send函数中设置了线程同步,所以说,每调用一次send,实际上都是巨大的性能消耗(此处用iocp发送亦然)。所以,要解决该问题, 最终还是要将小数据,组合成大数据,这样才能更高效率的发送。所以,DelaySender正是负责此类工作的。
使用DelaySender,会一定程度的降低发送的及时性,但是降低程度并不高,简单来说:
1. 如果一个包大于512kb,则不会延迟,直接发送。
2. 如果发送第一个包,与第二个包的时间间隔小于一个线程池线程调度的时间(这个时间极短,一般来说会在10**微秒**左右),则会将这两个包压缩为一个包发送。
#### UseReuseAddress
启用端口复用。该配置可在服务器、或客户端在监听端口时,运行监听同一个端口。可以一定程度缓解端口来不及释放的问题。
#### SetRemoteIPHost #### SetRemoteIPHost
链接到的远程IPHost,支持域名。支持类型: 链接到的远程IPHost,支持域名。支持类型:
...@@ -121,54 +80,102 @@ Ssl配置,为Null时则不启用。 ...@@ -121,54 +80,102 @@ Ssl配置,为Null时则不启用。
#### UseNoDelay #### UseNoDelay
设置Socket的NoDelay属性,默认false。 设置Socket的NoDelay属性,默认false。
#### UseBroadcast
该值指定可以发送或接收广播数据包。
</div> </div>
</details> </details>
## 五、支持插件 ## 五、支持插件
支持**ITcpPlugin**接口,或者继承自**TcpPluginBase**类,重写相应方法即可。
| 插件方法| 功能 | | 插件方法| 功能 |
| --- | --- | | --- | --- |
| OnConnecting | 在Socket完成初始化,但是并未连接时触发。 | | ITcpConnectingPlugin | 此时Socket实际上已经完成连接,但是并没有启动接收,然后触发。 |
| OnConnected | 在Socket完成连接,且成功后触发 | | ITcpConnectedPlugin | 同意连接,且成功启动接收后触发 |
| OnDisconnecting | 当客户端主动调用Close时触发 | | ITcpDisconnectingPlugin | 当客户端主动调用Close时触发 |
| OnDisconnected | 当客户端断开连接后触发 | | ITcpDisconnectedPlugin | 当客户端断开连接后触发 |
| OnReceivingData | 在收到原始数据时触发,所有的数据均在ByteBlock里面。 | | ITcpReceivingPlugin | 在收到原始数据时触发,所有的数据均在ByteBlock里面。 |
| OnReceivedData | 在收到适配器数据时触发,根据适配器类型,数据可能在ByteBlock或者IRequestInfo里面。 | | ITcpReceivedPlugin | 在收到适配器数据时触发,根据适配器类型,数据可能在ByteBlock或者IRequestInfo里面。 |
| OnSendingData | 当即将发送数据时,调用该方法在适配器之后,接下来即会发送数据。 | | ITcpSendingPlugin | 当即将发送数据时,调用该方法在适配器之后,接下来即会发送数据。 |
| IIdChangedPlugin | 当SocketClient的ID发生改变时触发。 |
## 六、创建TcpClient ## 六、创建TcpClient
#### 6.1 简单创建
简单的处理逻辑可通过**Connecting**、**Connected**、**Received**等委托直接实现。 简单的处理逻辑可通过**Connecting**、**Connected**、**Received**等委托直接实现。
代码如下: 代码如下:
```csharp ```csharp
TcpClient tcpClient = new TcpClient(); TcpClient tcpClient = new TcpClient();
tcpClient.Connected += (client, e) => { };//成功连接到服务器 tcpClient.Connecting = (client, e) => { };//即将连接到服务器,此时已经创建socket,但是还未建立tcp
tcpClient.Disconnected += (client, e) => { };//从服务器断开连接,当连接不成功时不会触发。 tcpClient.Connected = (client, e) => { };//成功连接到服务器
tcpClient.Received += (client, byteBlock, requestInfo) => tcpClient.Disconnecting = (client, e) => { };//即将从服务器断开连接。此处仅主动断开才有效。
tcpClient.Disconnected = (client, e) => { };//从服务器断开连接,当连接不成功时不会触发。
tcpClient.Received = (client, byteBlock, requestInfo) =>
{ {
//从服务器收到信息 //从服务器收到信息。但是一般byteBlock和requestInfo会根据适配器呈现不同的值。
string mes = Encoding.UTF8.GetString(byteBlock.Buffer, 0, byteBlock.Len); string mes = Encoding.UTF8.GetString(byteBlock.Buffer, 0, byteBlock.Len);
Console.WriteLine($"接收到信息:{mes}"); tcpClient.Logger.Info($"客户端接收到信息:{mes}");
}; };
//声明配置
TouchSocketConfig config = new TouchSocketConfig();
config.SetRemoteIPHost(new IPHost("127.0.0.1:7789"))
.UsePlugin();
//载入配置 //载入配置
tcpClient.Setup(config); tcpClient.Setup(new TouchSocketConfig()
tcpClient.Connect(); .SetRemoteIPHost("127.0.0.1:7789")
.ConfigureContainer(a =>
{
a.AddConsoleLogger();//添加一个日志注入
}));
tcpClient.Connect();//调用连接,当连接不成功时,会抛出异常。
//Result result = tcpClient.TryConnect();//或者可以调用TryConnect
//if (result.IsSuccess())
//{
//}
tcpClient.Logger.Info("客户端成功连接");
tcpClient.Send("RRQM"); tcpClient.Send("RRQM");
``` ```
#### 6.2 继承实现
一般继承实现的话,可以从TcpClientBase继承。
```csharp
class MyTcpClient: TcpClientBase
{
protected override bool HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
{
//此处逻辑单线程处理。
//此处处理数据,功能相当于Received委托。
string mes = Encoding.UTF8.GetString(byteBlock.Buffer, 0, byteBlock.Len);
Console.WriteLine($"已接收到信息:{mes}");
return true;//返回true,则表示该数据已被当前处理。不会再触发后续的插件等。
}
}
```
```csharp
MyTcpClient tcpClient = new MyTcpClient();
tcpClient.Connecting = (client, e) => { };//即将连接到服务器,此时已经创建socket,但是还未建立tcp
tcpClient.Connected = (client, e) => { };//成功连接到服务器
tcpClient.Disconnecting = (client, e) => { };//即将从服务器断开连接。此处仅主动断开才有效。
tcpClient.Disconnected = (client, e) => { };//从服务器断开连接,当连接不成功时不会触发。
//载入配置
tcpClient.Setup(new TouchSocketConfig()
.SetRemoteIPHost("127.0.0.1:7789")
.ConfigureContainer(a =>
{
a.AddConsoleLogger();//添加一个日志注入
}));
tcpClient.Connect();//调用连接,当连接不成功时,会抛出异常。
```
## 七、接收数据 ## 七、接收数据
在TcpClient中,接收数据的方式有很多种。多种方式可以组合使用。 在TcpClient中,接收数据的方式有很多种。多种方式可以组合使用。
...@@ -196,27 +203,25 @@ tcpClient.Setup(config); ...@@ -196,27 +203,25 @@ tcpClient.Setup(config);
tcpClient.Connect(); tcpClient.Connect();
``` ```
### 7.2 插件处理推荐 ### 7.2 插件处理 <Tag>推荐</Tag>
按照TouchSocket的设计理念,使用插件处理数据,是一项非常简单,且高度解耦的方式。步骤如下: 按照TouchSocket的设计理念,使用插件处理数据,是一项非常简单,且高度解耦的方式。步骤如下:
1. 服务器配置启用插件(UsePlugin) (1)声明插件
2. 新建插件类
3. 添加插件
代码如下: 插件可以先继承`PluginBase`,然后再实现需要的功能插件接口,可以按需选择泛型或者非泛型实现。
(1)声明插件 如果已经有继承类,直接实现`IPlugin`接口即可。
```csharp ```csharp
public class MyPlugin : TcpPluginBase<TcpClient> public class MyPlugin : PluginBase,ITcpReceivedPlugin<TcpClient>
{ {
public MyPlugin() public MyPlugin()
{ {
this.Order = 0;//此值表示插件的执行顺序,当多个插件并存时,该值越大,越在前执行。 this.Order = 0;//此值表示插件的执行顺序,当多个插件并存时,该值越大,越在前执行。
} }
protected override void OnReceivedData(TcpClient client, ReceivedDataEventArgs e) public void OnTcpReceived(TcpClient client, ReceivedDataEventArgs e)
{ {
//这里处理数据接收 //这里处理数据接收
//根据适配器类型,e.ByteBlock与e.RequestInfo会呈现不同的值,具体看文档=》适配器部分。 //根据适配器类型,e.ByteBlock与e.RequestInfo会呈现不同的值,具体看文档=》适配器部分。
...@@ -224,7 +229,11 @@ public class MyPlugin : TcpPluginBase<TcpClient> ...@@ -224,7 +229,11 @@ public class MyPlugin : TcpPluginBase<TcpClient>
IRequestInfo requestInfo = e.RequestInfo; IRequestInfo requestInfo = e.RequestInfo;
//e.Handled = true;//表示该数据已经被本插件处理,无需再投递到其他插件。 //e.Handled = true;//表示该数据已经被本插件处理,无需再投递到其他插件。
base.OnReceivedData(client, e); }
public Task OnTcpReceivedAsync(TcpClient client, ReceivedDataEventArgs e)
{
return Task.CompletedTask;
} }
} }
``` ```
...@@ -234,13 +243,12 @@ public class MyPlugin : TcpPluginBase<TcpClient> ...@@ -234,13 +243,12 @@ public class MyPlugin : TcpPluginBase<TcpClient>
```csharp ```csharp
TcpClient client = new TcpClient(); TcpClient client = new TcpClient();
client.Setup(new TouchSocketConfig() client.Setup(new TouchSocketConfig()
.SetRemoteIPHost(new IPHost("127.0.0.1:7789")) .SetRemoteIPHost("127.0.0.1:7789")
.UsePlugin() .ConfigureContainer(a =>
.ConfigureContainer(a=>
{ {
a.AddConsoleLogger(); a.AddConsoleLogger();
}) })
.ConfigurePlugins(a => .ConfigurePlugins(a =>
{ {
a.Add<MyPlugin>(); a.Add<MyPlugin>();
})) }))
...@@ -268,3 +276,9 @@ public virtual Task SendAsync(byte[] buffer); ...@@ -268,3 +276,9 @@ public virtual Task SendAsync(byte[] buffer);
public virtual Task SendAsync(byte[] buffer, int offset, int length); public virtual Task SendAsync(byte[] buffer, int offset, int length);
``` ```
:::tip 提示
框架不仅内置了`Send`字节的发送,也扩展了字符串等常见数据的发送。而且还包括了`TrySend`等不会抛出异常的发送方法。
:::
此差异已折叠。
--- ---
id: resetid id: resetid
title: 服务器重置ID title: 服务器重置id
--- ---
## 一、说明 ## 一、说明
每个客户端在连接时,服务器都会为连接的客户端**新分配**一个唯一的ID。也就是说,在服务器中ID与SocketClient实例就是一一对应的。 每个客户端在连接时,服务器都会为连接的客户端**新分配**一个唯一的Id。也就是说,在服务器中Id与SocketClient实例就是一一对应的。
## 二、配置初始ID策略 ## 二、配置初始Id策略
默认情况下服务器都会根据**历史连接数量**,为连接的客户端新分配ID。也就是说,第一个连接的,其ID就是1,以此类推。 默认情况下服务器都会根据**历史连接数量**,为连接的客户端新分配Id。也就是说,第一个连接的,其Id就是1,以此类推。
当然我们可以自由的定义ID策略,只需要在Config配置中,配置[SetGetDefaultNewID](../docs/createtcpservice.mdx#setgetdefaultnewid),自定义新ID来源即可。要求不和现连接的客户端ID重复。 当然我们可以自由的定义Id策略,只需要在Config配置中,配置[SetGetDefaultNewId](../docs/createtcpservice.mdx#setgetdefaultnewid),自定义新id来源即可。要求不和现连接的客户端id重复。
下列示例,就是使用Guid作为初始ID 下列示例,就是使用Guid作为初始Id
```csharp ```csharp
.SetGetDefaultNewID(()=> { return new Guid().ToString(); }) var config = new TouchSocketConfig();
config.SetGetDefaultNewId(()=>Guid.NewGuid().ToString());
``` ```
## 三、创建能代表连接的ID ## 三、创建能代表连接的Id
上述这种ID规范,是与连接信息没有任何关联的,这也就意味着,这种方式是无法关联SocketClient的。 上述这种Id规范,是与连接信息没有任何关联的,这也就意味着,这种方式是无法关联SocketClient的。
但往往,有时候,我们希望,SocketClient的ID,能一定程度的代表一些信息。例如:以客户端的IP和端口,作为唯一ID 但往往,有时候,我们希望,SocketClient的Id,能一定程度的代表一些信息。例如:以客户端的IP和端口,作为唯一id
那这时候,**服务器**可以订阅**Connecting**,然后,为新连接的SocketClient,设置与之有关联信息的ID 那这时候,**服务器**可以订阅**Connecting**,然后,为新连接的SocketClient,设置与之有关联信息的id
```csharp ```csharp
m_service.Connecting = (client, e) => m_service.Connecting = (client, e) => //有客户端正在连接
{ {
e.ID = $"{client.IP}:{client.Port}"; e.Id = $"{client.IP}:{client.Port}";
};//有客户端正在连接 };
``` ```
:::tip 提示 :::tip 提示
...@@ -40,23 +41,23 @@ m_service.Connecting = (client, e) => ...@@ -40,23 +41,23 @@ m_service.Connecting = (client, e) =>
::: :::
## 四、即时修改ID ## 四、即时修改id
上述修改ID的方式,应该还不足以应对所有情况。有时候我们希望,在该连接完成,且经过某种验证之后再设置新的ID,那么我们可以通过**ResetID**的方法,来实现需求。 上述修改Id的方式,应该还不足以应对所有情况。有时候我们希望,在该连接完成,且经过某种验证之后再设置新的id,那么我们可以通过**ResetId**的方法,来实现需求。
### 4.1 通过Service直接修改 ### 4.1 通过Service直接修改
```csharp ```csharp
service.ResetID("oldId","newId"); service.ResetId("oldId","newId");
``` ```
### 4.2 通过SocketClient修改 ### 4.2 通过SocketClient修改
```csharp ```csharp
socketClient.ResetID("newId"); socketClient.ResetId("newId");
``` ```
:::note 备注 :::note 备注
上述的ID标识,仅仅是服务器(TcpService)和辅助客户端(SocketClient)之间的关联。与客户端(TcpClient)是没有任何关系的。 上述的Id标识,仅仅是服务器(TcpService)和辅助客户端(SocketClient)之间的关联。与客户端(TcpClient)是没有任何关系的。
::: :::
\ No newline at end of file
---
id: tcpcommonplugins
title: 常用插件
---
\ No newline at end of file
...@@ -18,6 +18,22 @@ import Tag from "@site/src/components/Tag.js"; ...@@ -18,6 +18,22 @@ import Tag from "@site/src/components/Tag.js";
::: :::
## v1.5
更新日期:未定
更新描述:大版本更新。
- &nbsp;<Tag>优化</Tag> FileLogger支持指定不同目录。
- &nbsp;<Tag>优化</Tag> IPHost支持从int、string直接隐式转换。
- &nbsp;<Tag>调整</Tag> TouchSocket所有“ID”属性,改名为“Id”。
- &nbsp;<Tag>调整</Tag> TouchSocket所有插件的执行顺序,移动至内部重写方法之后。
- &nbsp;<Tag>调整</Tag> TouchSocket所有`ResetID`改名为`ResetId`。
- &nbsp;<Tag>移除</Tag> UsePlugin的显式配置,当调用ConfigurePlugins时,会自动启用。
- &nbsp;<Tag>新增</Tag> ws协议的TouchRpc服务端,增加HttpContext上下文获取。
---
## v1.3 ## v1.3
更新日期:2023.3.1 更新日期:2023.3.1
......
...@@ -17,20 +17,23 @@ title: 同步请求 ...@@ -17,20 +17,23 @@ title: 同步请求
### 2.1 以TcpClient为例 ### 2.1 以TcpClient为例
```csharp ```csharp
TcpClient m_tcpClient = new TcpClient(); TcpClient client = new TcpClient();
var config = new TouchSocketConfig(); client.Connect("127.0.0.1:7789");
config.SetRemoteIPHost(new IPHost("127.0.0.1:7789"));
//载入配置
m_tcpClient.Setup(config);
m_tcpClient.Connect();
//调用GetWaitingClient获取到IWaitingClient的对象。 //调用GetWaitingClient获取到IWaitingClient的对象。
var waitClient = m_tcpClient.GetWaitingClient(new WaitingOptions() var waitClient = client.GetWaitingClient(new WaitingOptions()
{ {
AdapterFilter = AdapterFilter.AllAdapter,//表示发送和接收的数据都会经过适配器 AdapterFilter = AdapterFilter.AllAdapter,//表示发送和接收的数据都会经过适配器
BreakTrigger = true,//表示当连接断开时,会立即触发 BreakTrigger = true,//表示当连接断开时,会立即触发
ThrowBreakException = true//表示当连接断开时,是否触发异常 ThrowBreakException = true//表示当连接断开时,是否触发异常
},
response => //设置用于筛选的fun委托,当返回为true时,才会响应返回
{
if (response.Data.Length==1)
{
return true;
}
return false;
}); });
//然后使用SendThenReturn。 //然后使用SendThenReturn。
...@@ -54,6 +57,14 @@ service.Received = (client, byteBlock, requestInfo) => ...@@ -54,6 +57,14 @@ service.Received = (client, byteBlock, requestInfo) =>
AdapterFilter = AdapterFilter.AllAdapter,//表示发送和接收的数据都会经过适配器 AdapterFilter = AdapterFilter.AllAdapter,//表示发送和接收的数据都会经过适配器
BreakTrigger = true,//表示当连接断开时,会立即触发 BreakTrigger = true,//表示当连接断开时,会立即触发
ThrowBreakException = true//表示当连接断开时,是否触发异常 ThrowBreakException = true//表示当连接断开时,是否触发异常
},
response => //设置用于筛选的fun委托,当返回为true时,才会响应返回
{
if (response.Data.Length==1)
{
return true;
}
return false;
}); });
//然后使用SendThenReturn。 //然后使用SendThenReturn。
......
...@@ -31,7 +31,7 @@ export default function (props) { ...@@ -31,7 +31,7 @@ export default function (props) {
}, },
移除: { 移除: {
icon: "shanchu", icon: "shanchu",
bgColor: "#666", bgColor: "red",
}, },
答疑: { 答疑: {
icon: "dayi", icon: "dayi",
......