Manuel
Manuel

Reputation: 675

C# TcpClient Networkstream read timeout - Recognize a String from ReadAsync (Telnet)

I am connecting to a remote Telnet Server using TcpClient and Networkstream, as long as the expected answer is delivered from the server everything works fine - however I would like to add a timeout, to catch an exception.

That's my current code, where I am waiting for "Username"

byte[] buffer = new byte[4096];

string response = "";
int bytesRead;

var cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.CancelAfter(5000); //does not work as timeout

while (!response.Contains("Username"))
{
    try
    {
        bytesRead = await targetClient.GetStream().ReadAsync(buffer, 0, buffer.Length, cancellationTokenSource.Token);
        response += Encoding.ASCII.GetString(buffer, 0, bytesRead);
        Console.WriteLine($"Answer from Telnet-Server: {response}");
    }
    catch
    {
        Console.WriteLine("catch");
        break;
    }
}

If I understand the ReadAsync function right - the cancellationToken is not taken into Account - so that's not how a timeout could be added.

Is there any possibility to add a timeout? Maybe some second Workerthread, which fires after 5 Seconds, and if the response does not contain "Username" I break out of the while loop? Or should I change the ReadAsync do a Synchronous Method, which supports a timeout? Or should I read everything from the Telnet Server into a Queue, and only ask if the Queue contains a relevant keyword, like "Username", would that be possible?

But I think there are much better approaches, right?

Thanks

Upvotes: 1

Views: 40

Answers (1)

Manuel
Manuel

Reputation: 675

I don't really know if this approach is OK, but it's working. Any comments if there are any pitfalls?

static async Task<string> WaitForPromptAsync(NetworkStream stream, string prompt, TimeSpan timeout)
{
    byte[] buffer = new byte[1024];
    StringBuilder response = new StringBuilder();
    DateTime startTime = DateTime.Now;

    while (DateTime.Now - startTime < timeout)
    {
        if (stream.DataAvailable)
        {
            int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);

            response.Append(Encoding.ASCII.GetString(buffer, 0, bytesRead));
           
            if (response.ToString().Contains(prompt))
            {
                return response.ToString();
            }
        }

        await Task.Delay(100); // is that OK?
    }

    return response.ToString();
}

vor example:

receivedData = await WaitForPromptAsync(stream, "Username", TimeSpan.FromSeconds(2));
if (receivedData.Contains("Username"))
{ //do something
}
else
{ //timeout occured
}

Upvotes: 0

Related Questions