Estoy implementando un cliente HTTP simple que solo se conecta a un servidor web y obtiene su página de inicio predeterminada. Aquí es agradable y funciona:Cliente HTTP realmente extraño usando TcpClient en C#
using System;
using System.Net.Sockets;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
TcpClient tc = new TcpClient();
tc.Connect("www.google.com", 80);
using (NetworkStream ns = tc.GetStream())
{
System.IO.StreamWriter sw = new System.IO.StreamWriter(ns);
System.IO.StreamReader sr = new System.IO.StreamReader(ns);
string req = "";
req += "GET/HTTP/1.0\r\n";
req += "Host: www.google.com\r\n";
req += "\r\n";
sw.Write(req);
sw.Flush();
Console.WriteLine("[reading...]");
Console.WriteLine(sr.ReadToEnd());
}
tc.Close();
Console.WriteLine("[done!]");
Console.ReadKey();
}
}
}
Al eliminar la línea de abajo desde arriba de código, los bloques de programa en sr.ReadToEnd.
req += "Host: www.google.com\r\n";
incluso sustituyen sr.ReadToEnd con sr.Read, pero no puede leer nada. Solía Wireshark para ver lo que suceda de:
Como se ve, después de mi solicitud GET Google no responde la solicitud y se retransmite una y otra vez. Parece que DEBEMOS especificar la parte Host en la solicitud HTTP. La parte rara es que NO LO HACEMOS. Usé telnet para enviar esta solicitud y recibí la respuesta de Google. También capturé la solicitud enviada por telnet y era exactamente lo mismo que mi pedido.
Probé en muchos otros sitios web (por ejemplo, Yahoo, Microsoft) pero el resultado es el mismo.
Por lo tanto, ¿el retraso en telnet hacer que el acto servidor web diferente (ya que en realidad nos telnet tipo de caracteres en lugar de enviarlos juntos en 1 paquete).
Otro problema es raro cuando cambio HTTP/1.0 a HTTP/1.1, el programa siempre bloques en sr.ReadToEnd línea. Supongo que es porque el servidor web no cierra la conexión.
Una solución es utilizar Leer (o ReadLine) y ns.DataAvailable para leer la respuesta. Pero no puedo estar seguro de haber leído toda la respuesta. ¿Cómo puedo leer la respuesta y estar seguro de que no quedan más bytes en la respuesta de una solicitud HTTP/1.1?
Nota: Como dice W3,
the Host request-header field MUST accompany all HTTP/1.1 requests
(y lo hice por mi HTTP/1.1 peticiones). Pero no he visto tal cosa para HTTP/1.0. También enviando una solicitud sin Host encabezado utilizando telnet funciona sin ningún problema.
Actualización:
empuje indicador se ha establecido en 1 en el segmento TCP. También intenté netsh winsock reset para restablecer mi pila de TCP/IP. No hay firewalls ni antivirus en la computadora de prueba. El paquete se envía realmente porque Wireshark instalado en otra computadora puede capturarlo.
También he intentado algunas otras solicitudes. Por ejemplo,
string req = "";
req += "GET/HTTP/1.0\r\n";
req += "s df slkjfd sdf/ s/fd \\sdf/\\\\dsfdsf \r\n";
req += "qwretyuiopasdfghjkl\r\n";
req += "Host: www.google.com\r\n";
req += "\r\n";
En todo tipo de peticiones, si omito el anfitrión : parte, el servidor web no responde y si con un Anfitrión: parte, incluso una solicitud válida (solo como la solicitud anterior) se responderá (mediante 400: HTTP Bad Request).
nos dice Host: no es necesario en su equipo, y esto hace que la situación sea más extraña.
No sé si este es el problema, pero no debería utilizar el contenido de longitud en la respuesta HTTP para determinar cuántos bytes debe leer, y luego leer los muchos bytes desde el cuerpo de la respuesta ? – Aziz
@Aziz. Quizás esta sea una buena solución en lugar de usar ** ReadToEnd **. Pero en la primera parte de la pregunta, no recibo nada (ni siquiera un byte) del servidor. – Isaac
Ese código funciona aquí con o sin el encabezado Host :. ¿El segmento TCP de la solicitud GET establece el bit PUSH? - No se puede hacer mucho al respecto, pero si no está configurado, podría explicar las retransmisiones – nos