且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

TcpClient或HttpWebRequest到Apple TV在30秒后结束?

更新时间:2023-12-03 21:01:16

我终于明白了.不是.Net代码终止了连接,而是Apple TV本身.通过Wireshark,在30秒钟内未在该连接上收到任何新消息后,我可以看到来自AppleTV的正确的Ack和Fin消息.为了解决该问题,我通过使用Telnet进行了摸索,发现AppleTV似乎并不在乎您发送的内容,只要您定期发送某些内容即可,这似乎可以使连接保持活动状态.

I figured it out finally. It wasn't the .Net code killing the connection, it was the Apple TV itself. With wireshark I was able to see the proper Ack and Fin messages which were from the AppleTV after 30 seconds of not recieving any new messages on that connection. To solve the problem I figured out by playing around with Telnet that the AppleTV doesn't seem to care what you send it as long as you send it SOMETHING on a periodic basis, which seems to keep the connection alive.

使用HttpWebRequest时,发送/接收部分相当固定.它是为标准的Http请求和响应而设计的,如果您需要执行其他任何操作,则只需启动一个新的HttpWebRequest而不使用现有的HttpWebRequest即可.尝试在相同的HttpWebRequest错误上发送第二条消息.

With HttpWebRequest the send/recieve portion is pretty canned. Its designed for a standard Http request and response, and if you need to do anything else you simply start a new HttpWebRequest rather than use the existing one. Trying to send a 2nd message on the same HttpWebRequest errors out.

因此,我不得不使用TcpClient,并且必须重做结尾.

So I had to use a TcpClient, and had to rework the end.

    /// <summary>
    /// Starts a video.
    /// </summary>
    /// <param name="url">The URL of the video to play.</param>
    /// <param name="startPosition">The start position of the video. This value must be between 0 and 1</param>
    public void StartVideo(Uri url, float startPosition = 0)
    {
        if (startPosition > 1)
        {
            throw new ArgumentException("Start Position must be between 0 and 1");
        }

        TcpClient tcpClient = new TcpClient("192.168.1.20", 7000);
        tcpClient.ReceiveTimeout = 100000;
        tcpClient.SendTimeout = 100000;

        //get the client stream to read data from.
        NetworkStream clientStream = tcpClient.GetStream();

        string body =
       "Content-Location: " + url + "\n" +
       "Start-Position: " + startPosition + "\n";

        string request = "POST /play HTTP/1.1\n" +
        "User-Agent: MediaControl/1.0\n" +
        "Content-Type: text/parameters\n" +
        "Content-Length: " + Encoding.ASCII.GetBytes(body).Length + "\n" +
        "X-Apple-Session-ID:" + _sessionGuid.ToString() + "\n\n";

        //Send the headers
        sendMessage(clientStream, request);
        //Send the body
        sendMessage(clientStream, body);

        //Get the response
        byte[] myReadBuffer = new byte[1024];
        StringBuilder myCompleteMessage = new StringBuilder();
        int numberOfBytesRead = 0;
        numberOfBytesRead = clientStream.Read(myReadBuffer, 0, myReadBuffer.Length);
        myCompleteMessage.Append(Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));

        //Now start doing a "keepalive"
        while (true)
        {
            //Simply send the characters "ok" every two seconds
            sendMessage(clientStream, "ok");
            Thread.Sleep(2000);
        }                      
    }

    /// <summary>
    /// Sends a message across the NetworkStream
    /// </summary>
    /// <param name="clientStream">The stream to send the message down</param>
    /// <param name="message">The message to send</param>
    public void sendMessage(NetworkStream clientStream, string message)
    {
        byte[] buffer = new ASCIIEncoding().GetBytes(message);
        try
        {
            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
        }
        catch (System.IO.IOException e)
        {
            Debug.WriteLine("IOException: " + e.Message);
        }
    }

显然,这不是最终的答案,但这是使它正常工作的最低要求.如果有人知道实际的Apple硬件代替确定"发送的是什么,请添加注释.

Obviously this is not the final answer, but this was the bare minimum to get it to work. If anybody figures out what the actual Apple hardware is sending in place of the "ok" please add a note.