2012-08-08 34 views
5

मैं अपने ऐप्पल टीवी पर विशेष रूप से जेनरेशन 3 के साथ काम करने के लिए एयरप्ले प्रोटोकॉल का उपयोग करने के लिए एयरप्ले प्रोटोकॉल का उपयोग करने के लिए सी # में एक लाइब्रेरी बनाने पर काम कर रहा हूं, लेकिन उम्मीद है कि इससे कोई फर्क नहीं पड़ता)।30 सेकंड के बाद समाप्त होने वाले ऐप्पल टीवी के लिए टीसीपी क्लाइंट या HttpWebRequest?

https://airlib.codeplex.com/

एयरप्ले के लिए आदेशों की इस कल्पना के अनुसार पोर्ट 70 पर HTTP हैं: http://nto.github.com/AirPlay.html

मैं एप्पल टीवी पर खेलने के लिए दोनों फ़ोटो और वीडियो के लिए हो रही में सफल रहे हैं, लेकिन कोई इससे कोई फर्क नहीं पड़ता कि मैं ऐप्पल टीवी केवल 30 सेकंड के वीडियो चलाऊंगा। ऐसा प्रतीत होता है कि मेरा सी # क्लाइंट जो प्ले कमांड को जारी करता है, 30 सेकेंड पर डिस्कनेक्ट हो रहा है, जिससे ऐप्पल टीवी प्ले सत्र समाप्त कर देता है।

कारण मैं इस बारे में सोच:

  • ग्राहक एप्लिकेशन को समाप्त पूरी तरह से 30 सेकंड इंतजार कर (अनिवार्य रूप से बंद करने के लिए कनेक्शन के लिए मजबूर) के रूप में ही व्यवहार पैदा करता है।
  • मैन्युअल रूप से HttpWebRequest या TcpClient कनेक्शन को बंद करना एक ही व्यवहार (एक प्ले सत्र के माध्यम से मिडवे) उत्पन्न करता है।
  • GetResponse() को रोकने के लिए ब्रेकपॉइंट को कितनी देर तक पकड़ने के बावजूद WebRequest संदेश भेजने शुरू होने के 30 मिनट बाद वीडियो को कॉल करता है।
  • वीडियो के लिए एक अलग स्रोत (आईआईएस, बाहरी वेबसर्वर) का उपयोग व्यवहार को नहीं बदलता है।
  • वीडियो के ऐप्पल टीवी पर कैश किए जाने के बाद भी और टाइमआउट को फिर से स्ट्रीम नहीं किया जाता है।

मुझे पूरा यकीन है कि क्लाइंट अनुरोध को वीडियो के "प्ले" में जुड़े रहने की आवश्यकता है, और मेरे सर्वोत्तम ज्ञान के लिए मैंने इसे करने के लिए कोड किया है। मैं वास्तव में अपने wits अंत में हूँ। मैंने उन सभी चीजों को आजमाया है जिनके बारे में मैं सोच सकता हूं कि HttpWebRequest और कच्चे टीसीपी क्लाइंट (जो दोनों काम करते हैं लेकिन दोनों बार बाहर होते हैं) के रूप में अनुरोध करते हैं, रेसीव/भेजें टाइमआउट को पागल संख्याओं पर सेट करते हैं, और टीसीपी स्ट्रीम के पढ़ने को लूप करते हैं यह सुनिश्चित करने के लिए कि "गतिविधि" है।

ऐसा लगता है कि ऐप्पलटीवी मुझे "हे, खेलना" संदेश भेजने की उम्मीद कर रहा है, लेकिन मुझे अभी तक वेब पर किसी भी स्रोत से ऐसा कुछ नहीं दिख रहा है। मुझे आशा है कि यह बस कुछ बेवकूफ है कि मैं एचटीपी/टीसीपी ज्ञान की कमी के आधार पर नहीं कर रहा हूं।

यहाँ मेरी कोड है:

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 

नोट: का उपयोग कर टेलनेट मैं इस आदेश को जो पूरे वीडियो निभाता में पेस्ट पोर्ट 7000 पर AppleTV से कनेक्ट करने में सक्षम हूँ और:

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 पर कैसिनी वेबसर्वर चला रहा हूं, लेकिन यह आईआईएस के साथ भी काम करता है। यह और सबूत प्रदान करता है कि नेट स्टैक 30 सेकंड में हुड के नीचे कुछ कर रहा है जो डिस्कनेक्ट का कारण बनता है।

उत्तर

5

मैंने अंत में इसे समझ लिया। यह .NET कोड कनेक्शन को मार नहीं रहा था, यह ऐप्पल टीवी ही था। वायरशर्क के साथ मैं उस कनेक्शन पर किसी भी नए संदेश प्राप्त करने के 30 सेकंड के बाद एप्पल टीवी से उचित एक और फिन संदेश देख सकता था। समस्या को हल करने के लिए मैंने टेलनेट के साथ खेलकर पता लगाया कि ऐप्पलटीवी उस परवाह नहीं कर रहा है जब तक आप इसे आवंटित आधार पर भेजते हैं, जो कि कनेक्शन को जीवित रखना प्रतीत होता है।

HttpWebRequest के साथ भेजने/प्राप्त करने वाला भाग सुंदर डिब्बाबंद है। यह एक मानक एचटीपी अनुरोध और प्रतिक्रिया के लिए डिज़ाइन किया गया है, और यदि आपको कुछ और करने की ज़रूरत है तो आप मौजूदा एक का उपयोग करने के बजाय बस एक नया HttpWebRequest शुरू करें। एक ही HttpWebRequest त्रुटियों पर एक दूसरा संदेश भेजने की कोशिश कर रहा है।

तो मुझे एक टीसीपी क्लाइंट का उपयोग करना पड़ा, और अंत को फिर से काम करना पड़ा।

/// <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); 
     } 
    } 

जाहिर है यह अंतिम जवाब नहीं है, लेकिन यह काम करने के लिए यह न्यूनतम था। यदि कोई व्यक्ति यह बताता है कि वास्तविक ऐप्पल हार्डवेयर "ठीक" के स्थान पर क्या भेज रहा है, तो कृपया एक नोट जोड़ें।

+0

एक Keep-Alive शीर्षलेख का उपयोग करना संभवतः हल करें? –

+0

वास्तव में यह पहली चीज थी जिसकी मैंने कोशिश की, दुर्भाग्य से मदद नहीं की। हालांकि महान विचार! – ExcaliburVT

+0

शायद आपके लिए बहुत देर हो चुकी है लेकिन अन्य लोगों के लिए सहायक: अपने सत्र के लिए "रिवर्स HTTP" लागू करें या प्लेबैक को जीवित रखने के लिए सिर्फ "/ स्क्रब" मतदान करें - फिल्म की अवधि और स्थिति प्राप्त करने के लिए स्क्रब भी उपयोगी है। – coyer