2015-11-15 14 views
0

Я пытаюсь сделать HTTP-запрос/ответ, используя сокеты в C#. Появится запрос GET.Пустое тело ответа HTTP

StringBuilder sb = new StringBuilder(); 
sb.AppendFormat("GET http://{0}/ HTTP/1.1\r\n", hostname); 
sb.AppendFormat("Host: {0}\r\n", hostname); 
sb.Append("Connection: keep-alive\r\n"); 
sb.Append(@"Accept:text/html,*/*"); 
sb.Append("\r\n\r\n"); 

где имя хоста что-то вроде 'mit.edu' или 'facebook.com' или 'google.com' или что-нибудь еще. По какой-то странной причине у меня есть только строка состояния (с кодом состояния 200) и заголовки как ответ http. Но нет никакого тела сообщения в ответ: attached srceenshot of my console app

Вот метод, который выполняет все манипуляции с розеткой и сделать запрос HTTP:

public static void DoHttpGetRequest(String hostname, Int16 port = 80) { 
     IPHostEntry ipHostEntry = Dns.GetHostEntry(hostname); 
     IPAddress ipAdress = ipHostEntry.AddressList[0]; 
     IPEndPoint ipEndPoint = new IPEndPoint(ipAdress, port); 

     Socket socket = new Socket(ipAdress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); 

     socket.Connect(ipEndPoint); 

     String request = CreateRequest(hostname); 

     Byte[] byteRequest = Encoding.UTF8.GetBytes(request); 
     Byte[] byteResponse = new Byte[1000]; 

     int bytesSent = socket.Send(byteRequest); 
     int bytesReceive = socket.Receive(byteResponse); 

     Console.WriteLine(request); 
     Console.WriteLine(); 
     Console.WriteLine(Encoding.UTF8.GetString(byteResponse, 0, bytesReceive)); 

     socket.Shutdown(SocketShutdown.Both); 
     socket.Close(); 
} 

Моя первая мысль была о том, что сокет не получил весь ответ от сервера. В этом случае я все еще не знаю, как решить проблему.

Так что же происходит? Где ошибка?

+0

Не знаете, какую услугу вы вызываете здесь, но если он дает вам http-код 200, что означает «ОК», то он должен что-то сделать. Вероятно, проблема на стороне сервера? Вы владеете услугой? Есть ли возможность просмотреть @ журнал или отследить код оттуда? –

+0

@ Теничный, спасибо за ответ. Сервиз не мой. Я много раз запускал код для разных сервисов. Есть senate.gov, ex.ua, mit.edu, google.com, fs.to и другие и другие из них. Все эти запросы получили ответы с кодом 200OK или 302Found или 301 и без тела сообщения. Поэтому я не уверен, что речь идет о проблеме на стороне сервера. – Yevtukhoff

ответ

1

Не ожидайте получения полного ответа внутри одного приема. То, что вы делаете, - это получать данные до тех пор, пока у вас не будет полного заголовка ответа (это может занять несколько вызовов приема), затем проанализируйте заголовок, чтобы узнать, как долго ответ, а затем прочитайте необходимые данные ответа, которые также могут потребоваться несколько принимать звонки. И поскольку вы выполняете запрос HTTP/1.1, вам также приходится иметь дело с чередующимися ответами.

Я рекомендую лучше использовать библиотеку HTTP для решения всех проблем. Если вы настаиваете на том, чтобы сделать все это самостоятельно, прочитайте the specification of HTTP и внесите соответствующие изменения. Это также помогает оглянуться на stackoverflow для подобных запросов, потому что эта проблема у вас очень типичная для тех, кто пытается внедрить HTTP в первый раз, не понимая, как работают сокеты, TCP и HTTP.

+0

RFC 2616 устарел («* Условное обозначение: 7230, 7231, 7232, 7233, 7234, 7235 *»). Для преемников читайте здесь: http://www.w3.org/Protocols/ и здесь https: //tools.ietf.org/html/rfc2616 – alk

+0

@alk: Я знаю, но легче указывать на один RFC, чем на несколько. И различия в спецификации между этими RFC незначительны, и любой браузер отличается от спецификации больше, чем старой и новой спецификацией. –

0

Я думаю, что вы должны держать розетку открытой в течение более длительного времени. Вставить a

Thread.Wait(5000); 

может помочь. Затем вы можете сделать второй сокет. Получите, как предложил Штеффен. Возможно, вы можете попробовать следующее (подождите, пока сервер не закроет соединение):

while (socket.Connected) do 
{ 
    int bytesReceive = socket.Receive(byteResponse); 
} 

Но я не проверял это. Легче использовать System.Net.Http.HttpClient

0

Все, что мне нужно сделать, это получить данные с несколькими приемами приема до получения всей полученной информации ответа.

do 
{     
    bytesReceive = socket.Receive(byteResponse, byteResponse.Length, 0); 
    response += Encoding.UTF8.GetString(byteResponse, 0, bytesReceive); 
} 
while (bytesReceive > 0); 

Всех за вашу помощь!

Смежные вопросы