我有一個TcpListener server可以通過呼叫server.AcceptTcpClientAsync(). 不幸的是,有隨機的、不需要的流量連接到我不關心的服務器,所以我添加了一個方法Task<bool> Handshake(TcpClient client)來驗證客戶端應該能夠與服務器通信。
獲得連接的幼稚方法是:
async Task<TcpClient> GetClient(TcpListener server)
{
while (true)
{
var client = await server.AcceptTcpClientAsync();
if (await Handshake(client))
{
return client;
}
client.Dispose();
}
}
不幸的是,握手程序在等待虛假連接時需要非零時間來超時,并且如果它花費的時間比下一個連接出現所需的時間長,掛起的連接將堆積起來并且永遠不會得到服務。
我知道 APITask.WhenAny允許同時運行多個異步操作,但我似乎無法為這個連接程序找到合適的模型。
我想要的是:
- 預計只有一次成功連接。
- 當連接到達時,嘗試握手。如果握手成功,則回傳它并處理任何其他掛起的連接。如果沒有,請處理連接。
- 正在進行的握手不應阻止回圈接受新連接。
- 進行中的握手次數總是可能為 0、1 或大于 1。
有什么好的方法可以用代碼表達這一點嗎?
uj5u.com熱心網友回復:
您可以Channel用于安全的跨執行緒通信
var channel = Channel.CreateBounded<TcpClient>(100);
var writer = channel.Writer;
var reader = channel.Reader;
_ = GetClient(server);
var successClient = await Task.Run(async () =>
{
await foreach (var client in reader.ReadAllAsync())
{
if (await Handshake(client))
{
return client;
}
client.Dispose();
}
return null;
});
//mark the channel that no more data is going to be written to it
writer.TryComplete();
//run through the remaining clients in the channel and dispose of them
await foreach (var client in reader.ReadAllAsync())
{
client.Dispose();
}
//use successClient here
async Task<TcpClient> GetClient(TcpListener server)
{
while (true)
{
var client = await server.AcceptTcpClientAsync();
await writer.WriteAsync(client);
}
}
uj5u.com熱心網友回復:
首先,您可以使用Task.Run執行任務,這樣您就不必在那里等待。然后你可以使用ContinueWith回呼來處理成功的握手。接下來,您可以維護要處理的連接串列。另外,我建議在回圈時添加一些延遲,
async Task<TcpClient> GetClient(TcpListener server)
{
List<Task<Client>> _clients=new();
bool handshakeCompleted=false;
Client workingClient=null;
while (!handshakeCompleted)
{
var client = Task.Run(async ()=> await server.AcceptTcpClientAsync());
client.ContinueWith(async ()=>
{
if (await Handshake(client))
{
handshakeCompleted=true;
workingClient=client;
}
});
_clients.Add(client);
await Task.Delay(10);
}
foreach(var c in _clients.Where(c!=workingClient)) c.Dispose();
return workingClient;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/376380.html
