2009-07-04 2 views
14

Я пытаюсь использовать классы .NET WebRequest/WebResponse для доступа к API потоковой передачи Twitter здесь "http://stream.twitter.com/spritzer.json".Чтение данных из открытого HTTP-потока

Мне нужно иметь возможность открывать соединение и читать данные пошагово от открытого соединения.

В настоящее время, когда я вызываю метод WebRequest.GetResponse, он блокируется до тех пор, пока не будет загружен весь ответ. Я знаю, что есть метод BeginGetResponse, но это будет делать то же самое в фоновом потоке. Мне нужно получить доступ к потоку ответов во время загрузки. Мне это не кажется возможным с этими классами.

Существует конкретный комментарий по этому поводу в документации Twitter:

«Пожалуйста, обратите внимание, что некоторые клиентские библиотеки HTTP возвращают только тело ответа после того, как соединение было закрыто сервером Эти клиенты не будут работать для доступа. Streaming API. Вы должны использовать HTTP-клиент, который будет постепенно возвращать данные ответа. Большинство надежных клиентских библиотек HTTP предоставят эту функцию. Например, Apache HttpClient будет обрабатывать этот вариант использования ».

Они указывают на Appache HttpClient, но это мало помогает, потому что мне нужно использовать .NET.

Любые идеи, возможно ли это с помощью WebRequest/WebResponse, или мне нужно идти на сетевые классы более низкого уровня? Может быть, есть другие библиотеки, которые позволят мне это сделать?

Thx Allen

ответ

0

Вы пробовали WebRequest.BeginGetRequestStream()?

Или что-то вроде этого:

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

я не могу использовать WebRequest.BeginGetRequestStream, потому что я Я не пытаюсь записывать данные асинхронно на сервер. Кроме того, в вашем примере вы вызываете GetResponse. Именно в этот момент WebRequest блокируется, пока он загружает ответ сервера. Но соединение никогда не закрывается, потому что это эффективно бесконечный поток данных. – user108687

-2

Просто используйте WebClient. Он предназначен для таких простых случаев, когда вам не нужна полная мощность WebRequest.

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

Как именно веб-клиент позволяет мне получать инкрементные данные из открытого потокового HTTP-соединения? Все методы WebClient.Download * пытаются загрузить весь ответ. Мне нужно взять инкрементные блоки бесконечного потока HTTP-данных. – user108687

+0

О, вам нужно передавать данные? Виноват. –

+0

Отрицательный результат ...Вы должны прочитать вопрос, прежде чем ответить на него :( –

13

В итоге я использовал TcpClient, который отлично работает. Было бы интересно узнать, возможно ли это с помощью WebRequest/WebResponse. Вот мой код в случае, если кто-нибудь интересуется:

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

Нужно ли «\ r \ n»? –

+4

Да, HTTP - это протокол, ориентированный на линию. Вам нужно отделить команды от \ r \ n. – Viet

+0

Является ли поток, возвращаемый клиентом. GetStream() фактически потоковелся из сетевого стека или это просто кешированный поток памяти? –

5

BeginGetResponse метод вам нужно. Это позволяет считывать поток ответа пошагово:

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

Или, если вы чувствуете себя более комфортно с WebClient (я Personnally предпочитаю его над 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

Я не пробовал это, потому что предположил, что req.EndGetResponse будет блокироваться точно так же, как это делает req.GetResponse, оставив меня с той же проблемой – user108687

+0

Я пробовал это без везения. Поток, возвращаемый .GetResponseStream() - это MemoryStream, содержащий все содержимое ответа. – Jeb

+0

@Darin Dimitrov, Как вы справляетесь с таймаутами, если есть длинные периоды времени между данными, поступающими в поток? –