C#tcp socket keepalive

时间:2016-12-18 14:55:53

标签: c# sockets

我在C#中创建一个客户端应用程序,用于通过telnet协议将命令发送到远程路由器。目前,远程路由器关闭空闲连接2~5分钟。我正在寻找一种方法来保持我的联系。 我试过以下代码:

socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

但它不起作用。

这是我的TelnetClient代码:

public class TelnetClient
{
    private NetworkStream ns;
    private Socket client;
    private const string prompt = ">";
    private const int buffer = 2048;
    private string host;
    private int port;
    private string user;
    private string password;

    public TelnetClient(string host, int port, string user, string password)
    {
        client = new Socket(SocketType.Stream, ProtocolType.Tcp);

        client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
        this.host = host;
        this.port = port;
        this.user = user;
        this.password = password;
    }


    public bool Connect()
    {
        try
        {
            client.Connect(host, port); 
            ns = new NetworkStream(client);

            return true;
        }
        catch (Exception e)
        {
            Trace.TraceError(e.Message);

            return false;
        }
    }

    public bool Login()
    {
        Write(this.user);
        ReadUntil(":", 1000);
        Write(this.password);
        if(ReadUntil(">", 1000) != null)
            return true;
        return false;
    }

    public string ReadUntil(string pattern, long timeout)
    {
        StringBuilder sb = new StringBuilder();
        string text = "";
        byte[] arr = new byte[buffer];

        try
        {
            if (ns.CanRead)
            {
                Stopwatch s = new Stopwatch();
                s.Start();
                while (s.Elapsed < TimeSpan.FromMilliseconds(timeout))
                {
                    text = sb.ToString().Trim().ToLower();

                    if (pattern.Length > 0 && text.ToLower().Trim().EndsWith(pattern))
                    {
                        return text.ToLower();
                    }

                    if (ns.DataAvailable)
                    {
                        int count = ns.Read(arr, 0, arr.Length);
                        sb.AppendFormat("{0}", Encoding.ASCII.GetString(arr, 0, count));
                    }
                }
            }
            else
                return null;
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.Message);
        }
        return null;
    }

    public void Write(string value)
    {
        byte[] arr = Encoding.ASCII.GetBytes(value + Environment.NewLine);



        try
        {
            ns.Write(arr, 0, arr.Length);
            ns.Flush();
            System.Threading.Thread.Sleep(1000);
        }
        catch (Exception e)
        {
            Trace.TraceError(e.Message);
        }
    }

    public string SendCommand(string cmd, int timeout)
    {
        Write(cmd);
        return ReadUntil(prompt, timeout);
    }

    public void Disconnect()
    {
        try
        {
            byte[] arr = Encoding.ASCII.GetBytes("exit" + Environment.NewLine);
            ns.Write(arr, 0, arr.Length);
            ns.Close();
            client.Close();
        }
        catch (Exception e)
        {
            Trace.TraceError(e.Message);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

在我的团队的一个产品上,我们发现TCP保持活动间隔的频率不够高,足以使某些NAT的路由器端口保持打开状态。

我们更新了协议以发送“ping”消息,该消息每45秒响应一次“pong”。但那是我们控制的协议。

对于telnet,最好的办法是在每个间隔发送telnet转义字符,然后发送NOP(241)或AYT(246)的telnet命令。有关更多详细信息,请参阅RFC 854。