---
id: waitingclient
title: 同步请求
---

## 一、说明

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

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

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

## 二、创建及使用

### 2.1 以TcpClient为例

```csharp
TcpClient m_tcpClient = new TcpClient();
var config = new TouchSocketConfig();
config.SetRemoteIPHost(new IPHost("127.0.0.1:7789"));

//载入配置
m_tcpClient.Setup(config);
m_tcpClient.Connect();

//调用GetWaitingClient获取到IWaitingClient的对象。
var waitClient = m_tcpClient.GetWaitingClient(new WaitingOptions()
{
    AdapterFilter = AdapterFilter.AllAdapter,//表示发送和接收的数据都会经过适配器
    BreakTrigger = true,//表示当连接断开时，会立即触发
    ThrowBreakException = true//表示当连接断开时，是否触发异常
});

//然后使用SendThenReturn。
byte[] returnData = waitClient.SendThenReturn(Encoding.UTF8.GetBytes("RRQM"));
m_tcpClient.Logger.Info($"收到回应消息：{Encoding.UTF8.GetString(returnData)}");

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

### 2.2 以TcpService为例

```csharp
var service = new TcpService();
service.Received = (client, byteBlock, requestInfo) =>
{
    //调用GetWaitingClient获取到IWaitingClient的对象。
    var waitClient = client.GetWaitingClient(new WaitingOptions()
    {
        AdapterFilter = AdapterFilter.AllAdapter,//表示发送和接收的数据都会经过适配器
        BreakTrigger = true,//表示当连接断开时，会立即触发
        ThrowBreakException = true//表示当连接断开时，是否触发异常
    });

    //然后使用SendThenReturn。
    byte[] returnData = waitClient.SendThenReturn(Encoding.UTF8.GetBytes("RRQM"));
    client.Logger.Info($"收到回应消息：{Encoding.UTF8.GetString(returnData)}");

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

service.Setup(new TouchSocketConfig()//载入配置     
    .SetListenIPHosts(new IPHost[] { new IPHost("tcp://127.0.0.1:7789"), new IPHost(7790) })//同时监听两个地址
    .ConfigureContainer(a =>//容器的配置顺序应该在最前面
    {
        a.AddConsoleLogger();//添加一个控制台日志注入（注意：在maui中控制台日志不可用）
    })
    .ConfigurePlugins(a =>
    {
        //a.Add();//此处可以添加插件
    }))
    .Start();//启动
```

:::tip 提示

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

:::  

:::tip 提示

实际上上述行为，只要实现IClient, IDefaultSender, ISend三个接口的类均可以使用。

:::  

:::danger 注意事项

1. 发送完数据，在等待时，如果收到其他返回数据，则可能得到错误结果。
2. 发送采用Lock锁，一个事务没结束，另一个请求也发不出去。

:::