Well, I need to connect to a TCP socket, however, it only accepts one connection at a time and has a 60 second timeout.
The problem is that in the process of sending information and receiving a response, the application is not performative.
I would like to know, if in this case, it is possible to do something asynchronous/parallel.
Below is my socket client class.
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();
}
}
You can modify your code to be async:
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;
}
To call it use:
MyFrameResponseType response = await SendRequest(yourRequest);
Also, as a note, that code assumes you will receive a response with only one read, that will fail on a future, if the network is slow or the sent response is big enough it will be received in multiple read operations, you should have some mechanism to detect a frame start/end and read until you have received a full frame.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.