TcpClient的或HttpWebRequest的到Apple TV 30秒后结束?(TcpCli

2019-06-26 20:56发布

我正在建立在C#中的图书馆使用的Airplay协议来发送照片和视频到我的苹果电视(特别是与第3代的工作,但希望这不应该的问题此)。

https://airlib.codeplex.com/

所有的Airplay的命令是HTTP端口70按照该规范: http://nto.github.com/AirPlay.html

我已经成功地获取照片和视频到Apple TV上播放,但无论我做什么AppleTV的只能打30秒钟的视频。 它看起来好像我的C#客户端发出播放命令切断右为30秒,这将导致AppleTV的结束游戏会话。

原因我想这样的:

  • 终止所述客户端应用程序完全产生相同的行为作为等待30秒(实质上迫使连接关闭)。
  • 手动关闭的HttpWebRequest或TcpClient的连接产生相同的行为(中途戏剧会话)。
  • 无论多久,我持断点防止的GetResponse()调用视频总是超时30秒开始的WebRequest发送消息之后。
  • 使用视频不同的源(IIS,部服务器)不会改变的行为。
  • 在视频缓存在AppleTV的,即使后不会重新流超时仍会发生。

我敢肯定,在客户端请求需要保持连接整个影片的“戏”,并以我所知,我已经编写它这样做。 我真的在我束手无策。 我已经试过,我能想到的,包括做请求既作为HttpWebRequest和作为原料的TcpClient(两者的工作,但都超时)的一切,设置收到/发送超时,以疯狂的数字,和循环的TCP流的读确保有“活动”。

它仿佛AppleTV的期待我送一“哎,陪玩”的消息,但我还没有看到这样的事情从网络上的任何来源。 我希望,这仅仅是愚蠢的东西,我不是在做基于我缺乏HTTP / TCP知识。

这里是我的代码:

    Uri url = "http://somevideo.com/video.mov";
    float startPosition = 0;        
    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";

    sendMessage(clientStream, request);
    sendMessage(clientStream, body);

    byte[] myReadBuffer = new byte[1024];
    StringBuilder myCompleteMessage = new StringBuilder();
    int numberOfBytesRead = 0;

    //incoming message might be bigger than the buffer
    do
    {
        try
        {
            numberOfBytesRead = clientStream.Read(myReadBuffer, 0, myReadBuffer.Length);
            myCompleteMessage.Append(Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));
            Thread.Sleep(10);//let the iOS device catch up sending data
        }
        catch (System.IO.IOException) { }
    } while (tcpClient.Connected); //check if it's connected before checking for data available, as maybe the program might get quit and the sockets closed halfway through a read

注意:使用telnet我能够连接到AppleTV的端口7000和在此命令,其播放整个视频贴:

POST /play HTTP/1.1
User-Agent: MediaControl/1.0
Content-Type: text/parameters
Content-Length: 89
X-Apple-Session-ID:fb6d816a-a5ad-4e8f-8830-9642b6e6eb35

Content-Location: http://192.168.1.11:82/2012/2012_03_11/IMG_1328.MOV
Start-Position: 0

我在端口82上运行的卡西尼Web服务器,但是这还与IIS。 这提供了进一步的证据表明,净栈在30秒造成脱节做引擎盖下的东西。

Answer 1:

我想通了最后。 这不是Net代码查杀连接,这是苹果电视本身。 使用Wireshark我能看到这是从AppleTV的该连接上不recieving任何新的消息的3​​0秒后正确的确认和FIN消息。 为了解决我通过远程登录玩弄了AppleTV的似乎并不关心你,只要你把它定期,这似乎保持连接上的东西把它想通了这个问题。

随着HttpWebRequest的发送/收到部分是相当罐头。 它为一个标准的HTTP请求和响应而设计的,如果你需要做别的你只需启动一个新的HttpWebRequest,而不是使用现有的一个。 尝试发送同一HttpWebRequest的误差的第二消息出来。

所以,我不得不使用TcpClient的,只好返工结束。

    /// <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硬件代替的“OK”送请添加备注。



文章来源: TcpClient or HttpWebRequest to Apple TV ending after 30 seconds?