跳到主要内容
版本:3.0

同步请求

定义

命名空间:TouchSocket.Sockets
程序集:TouchSocket.dll

一、说明

有很多小伙伴一直有一些需求:

  1. 客户端发送一个数据,然后等待服务器回应。
  2. 服务器向客户端发送一个数据,然后等待客户端回应。

那针对这些需求,可以使用WaitingClient。其内部实现了IWaitSender接口,能够在发送完成后,等待返回。

二、创建及使用

2.1 以TcpClient为例

var client = new TcpClient();
await client.ConnectAsync("tcp://127.0.0.1:7789");

//调用CreateWaitingClient获取到IWaitingClient的对象。
var waitClient = client.CreateWaitingClient(new WaitingOptions()
{
FilterFunc = response => //设置用于筛选的fun委托,当返回为true时,才会响应返回
{
return true;

//if (response.Data.Length == 1)
//{
// return true;
//}
//return false;
}
});

//然后使用SendThenReturn。
byte[] returnData = await waitClient.SendThenReturnAsync(Encoding.UTF8.GetBytes("RRQM"));
Console.WriteLine($"收到回应消息:{Encoding.UTF8.GetString(returnData)}");

//同时,如果适配器收到数据后,返回的并不是字节,而是IRequestInfo对象时,可以使用SendThenResponse.
ResponsedData responsedData = await waitClient.SendThenResponseAsync(Encoding.UTF8.GetBytes("RRQM"));
IRequestInfo requestInfo = responsedData.RequestInfo;//同步收到的RequestInfo

2.2 以TcpService为例

var service = new TcpService();
await service.StartAsync(7789);//启动服务器

//在服务器中,找到指定Id的会话客户端
if (service.TryGetClient("targetId", out var tcpSessionClient))
{
//调用CreateWaitingClient获取到IWaitingClient的对象。
var waitClient = tcpSessionClient.CreateWaitingClient(new WaitingOptions()
{
FilterFunc = response => //设置用于筛选的fun委托,当返回为true时,才会响应返回
{
return true;

//if (response.Data.Length == 1)
//{
// return true;
//}
//return false;
}
});

//然后使用SendThenReturn。
byte[] returnData = await waitClient.SendThenReturnAsync(Encoding.UTF8.GetBytes("RRQM"));
Console.WriteLine($"收到回应消息:{Encoding.UTF8.GetString(returnData)}");

//同时,如果适配器收到数据后,返回的并不是字节,而是IRequestInfo对象时,可以使用SendThenResponse.
ResponsedData responsedData = await waitClient.SendThenResponseAsync(Encoding.UTF8.GetBytes("RRQM"));
IRequestInfo responseRequestInfo = responsedData.RequestInfo;//同步收到的RequestInfo
}
提示

在SendThenReturnAsync时,通过其他参数,还可以设置Timeout,以及可取消的等待Token。

注意

所有的发送,框架内部实际上只实现了异步发送,但是为了兼容性,仍然保留了同步发送的扩展。但是强烈建议如有可能,请务必使用异步发送来提高效率

注意事项
  1. 发送完数据,在等待时,如果收到其他返回数据,则可能得到错误结果。
  2. 发送采用同步锁,一个事务没结束,另一个请求也发不出去。
  3. waitClient的使用不可以直接在Received相关触发中使用,因为必然会导致死锁,详见:#I9GCGT
  4. Net461及以下版本中,SendThenReturn与SendThenReturnAsync不能混合使用。即:要么全同步,要么全异步(这可能是.net bug)。

本文示例Demo