异步TCP套接字问题

时间:2018-04-18 19:56:44

标签: c# sockets asynchronous parallel-processing

好吧,我需要连接到TCP套接字,但是,它一次只接受一个连接,并且有60秒的超时。

问题在于,在发送信息和接收响应的过程中,应用程序不具有表现性。

我想知道,如果在这种情况下,可以执行异步/并行操作。

以下是我的套接字客户端类。

public class TcpSocketClient
{
    public TcpClient TCPConnection { get; private set; }

    private int BUFFER_SIZE = 259;

    public TcpSocketClient Connect(IPEndPoint endpoint)
    {
        try
        {
            this.TCPConnection = new TcpClient(endpoint);
            return this;
        }
        catch (SocketException ex)
        {
            throw new Exception($"{ex.Message} - {ex.StackTrace}");
        }
        catch (Exception ex)
        {
            throw new Exception($"Err: {ex.Message} - {ex.StackTrace}");
        }
    }

    public T SendRequest<T>(IFrame request) where T : IFrame, new()
    {
        var data = request.ToByteArray();

        var stream = this.TCPConnection.GetStream();
        stream.Write(data, 0, data.Length);

        data = new byte[this.BUFFER_SIZE];
        var quantityBytes = stream.Read(data, 0, data.Length);

        var frameResponse = data.Take(quantityBytes).ToArray();

        var response = new T
        {
            FrameHeader = frameResponse[0],
            Lenght = frameResponse[1],
            FunctionCode = frameResponse[2],
            Data = (frameResponse[1] == 0) ? null : data.ToDataField(quantityBytes),
            Checksum = frameResponse[frameResponse.Length - 1]
        };

        (response.Checksum != response.VerifyChecksum()) { throw new Exception("Err in Checksum!"); }

        return response;
    }

    public void Disconnect()
    {
        this.TCPConnection.Dispose();
    }
}

1 个答案:

答案 0 :(得分:0)

您可以将代码修改为异步:

public async Task<T> SendRequest<T>(IFrame request) where T : IFrame, new()
{
    var data = request.ToByteArray();

    var stream = this.TCPConnection.GetStream();
    await stream.WriteAsync(data, 0, data.Length);

    data = new byte[this.BUFFER_SIZE];
    var quantityBytes = await stream.ReadAsync(data, 0, data.Length);

    var frameResponse = data.Take(quantityBytes).ToArray();

    var response = new T
    {
        FrameHeader = frameResponse[0],
        Lenght = frameResponse[1],
        FunctionCode = frameResponse[2],
        Data = (frameResponse[1] == 0) ? null : data.ToDataField(quantityBytes),
        Checksum = frameResponse[frameResponse.Length - 1]
    };

    if(response.Checksum != response.VerifyChecksum())
        throw new Exception("Err in Checksum!");

    return response;
}

要使用它:

MyFrameResponseType response = await SendRequest(yourRequest);

另外,作为一个注释,该代码假定您将收到只有一次读取的响应,如果网络速度很慢或发送的响应足够大,将在多次读取操作中接收,将来会失败。你应该有一些机制来检测帧的开始/结束并读取,直到你收到一个完整的帧。