2009-07-04 12 views
14

Sto tentando di utilizzare le classi .NET WebRequest/WebResponse per accedere all'API di streaming di Twitter qui "http://stream.twitter.com/spritzer.json".Lettura di dati da un flusso HTTP aperto

Devo essere in grado di aprire la connessione e leggere i dati in modo incrementale dalla connessione aperta.

Attualmente, quando chiamo il metodo WebRequest.GetResponse, blocca fino a quando non viene scaricata l'intera risposta. So che esiste un metodo BeginGetResponse, ma questo farà semplicemente la stessa cosa su un thread in background. Devo accedere al flusso di risposta mentre il download è ancora in corso. Questo non mi sembra possibile con queste lezioni.

C'è un commento specifiche su questo nella documentazione di Twitter:

"Si prega di notare che alcune librerie client HTTP restituiscono solo il corpo di risposta dopo che la connessione è stata chiusa dal server Questi clienti non funzionerà per l'accesso. l'API di streaming.È necessario utilizzare un client HTTP che restituirà i dati di risposta in modo incrementale.Le librerie client HTTP più robuste forniranno questa funzionalità.Il Apache HttpClient gestirà questo caso d'uso, ad esempio. "

Puntano a HttpClient di Appache, ma questo non aiuta molto perché ho bisogno di utilizzare .NET.

Qualche idea se questo sia possibile con WebRequest/WebResponse o devo andare per le classi di rete di livello inferiore? Forse ci sono altre librerie che mi permetteranno di fare questo?

Thx Allen

risposta

0

Hai provato WebRequest.BeginGetRequestStream()?

O qualcosa di simile:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create (http://www.twitter.com); 
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
StreamReader reader = new StreamReader(response.GetResponseStream()); 

string str = reader.ReadLine(); 
while(str != null) 
{ 
    Console.WriteLine(str); 
    str = reader.ReadLine(); 
} 
+0

non posso usare perché io WebRequest.BeginGetRequestStream non sto cercando di scrivere dati in modo asincrono sul server. Inoltre, nel tuo esempio chiami GetResponse. È a questo punto che WebRequest sta bloccando mentre scarica la risposta del server. Ma la connessione non si chiude mai perché è un flusso di dati effettivamente infinito. – user108687

-2

Basta usare WebClient. È progettato per casi semplici come questo in cui non hai bisogno della piena potenza di WebRequest.

System.Net.WebClient wc = new System.Net.WebClient(); 
Console.WriteLine(wc.DownloadString("http://stream.twitter.com/spritzer.json")); 
+0

In che modo esattamente il client Web consente di acquisire dati incrementali da una connessione HTTP in streaming aperta? Tutti i metodi WebClient.Download * tentano di scaricare l'intera risposta. Ho bisogno di prendere blocchi incrementali di un flusso infinito di dati HTTP. – user108687

+0

Oh, hai bisogno di dati in streaming? Colpa mia. –

+0

Punteggio negativo ...È necessario leggere la domanda prima di rispondere :( –

13

Ho finito per utilizzare un TcpClient, che funziona bene. Sarebbe comunque interessante sapere se ciò è possibile con WebRequest/WebResponse. Ecco il mio codice nel caso in cui qualcuno è interessato:

using (TcpClient client = new TcpClient()) 
{ 

string requestString = "GET /spritzer.json HTTP/1.1\r\n"; 
requestString += "Authorization: " + token + "\r\n"; 
requestString += "Host: stream.twitter.com\r\n"; 
requestString += "Connection: keep-alive\r\n"; 
requestString += "\r\n"; 

client.Connect("stream.twitter.com", 80); 

using (NetworkStream stream = client.GetStream()) 
{ 
    // Send the request. 
    StreamWriter writer = new StreamWriter(stream); 
    writer.Write(requestString); 
    writer.Flush(); 

    // Process the response. 
    StreamReader rdr = new StreamReader(stream); 

    while (!rdr.EndOfStream) 
    { 
     Console.WriteLine(rdr.ReadLine()); 
    } 
} 
} 
+0

È necessario \ r \ n? –

+4

Sì, HTTP è un protocollo orientato alla linea. È necessario separare i comandi da \ r \ n. – Viet

+0

Lo stream restituito dal client. GetStream() effettivamente trasmesso dallo stack di rete o è solo un flusso di memoria memorizzato nella cache? –

5

BeginGetResponse è il metodo che vi serve. Esso consente di leggere il flusso di risposta in modo incrementale:

class Program 
{ 
    static void Main(string[] args) 
    { 
     WebRequest request = WebRequest.Create("http://stream.twitter.com/spritzer.json"); 
     request.Credentials = new NetworkCredential("username", "password"); 
     request.BeginGetResponse(ar => 
     { 
      var req = (WebRequest)ar.AsyncState; 
      // TODO: Add exception handling: EndGetResponse could throw 
      using (var response = req.EndGetResponse(ar)) 
      using (var reader = new StreamReader(response.GetResponseStream())) 
      { 
       // This loop goes as long as twitter is streaming 
       while (!reader.EndOfStream) 
       { 
        Console.WriteLine(reader.ReadLine()); 
       } 
      } 
     }, request); 

     // Press Enter to stop program 
     Console.ReadLine(); 
    } 
} 

o se si sente più a suo agio con WebClient (ho personalmente preferisce sopra WebRequest):

using (var client = new WebClient()) 
{ 
    client.Credentials = new NetworkCredential("username", "password"); 
    client.OpenReadCompleted += (sender, e) => 
    { 
     using (var reader = new StreamReader(e.Result)) 
     { 
      while (!reader.EndOfStream) 
      { 
       Console.WriteLine(reader.ReadLine()); 
      } 
     } 
    }; 
    client.OpenReadAsync(new Uri("http://stream.twitter.com/spritzer.json")); 
} 
Console.ReadLine(); 
+0

Non ho provato questo perché ho pensato che req.EndGetResponse avrebbe bloccato esattamente nello stesso modo req.GetResponse, lasciandomi con lo stesso problema Io lo proverò – user108687

+0

L'ho provato senza fortuna Lo stream restituito da .GetResponseStream() è un MemoryStream contenente l'intero contenuto della risposta – Jeb

+0

@Darin Dimitrov, Come gestite i timeout se ci sono lunghi periodi di tempo tra i dati che arrivano sul flusso? –