net example data create c# sockets httpwebrequest httpwebresponse

example - webrequest stream c#



Zócalos en C#: ¿cómo obtener la secuencia de respuesta? (3)

Estoy tratando de reemplazar esto:

void ProcessRequest(object listenerContext) { var context = (HttpListenerContext)listenerContext; Uri URL = new Uri(context.Request.RawUrl); HttpWebRequest.DefaultWebProxy = null; HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(URL); httpWebRequest.Method = context.Request.HttpMethod; httpWebRequest.Headers.Clear(); if (context.Request.UserAgent != null) httpWebRequest.UserAgent = context.Request.UserAgent; foreach (string headerKey in context.Request.Headers.AllKeys) { try { httpWebRequest.Headers.Set(headerKey, context.Request.Headers[headerKey]); } catch (Exception) { } } using (HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse()) { Stream responseStream = httpWebResponse.GetResponseStream(); if (httpWebResponse.ContentEncoding.ToLower().Contains("gzip")) responseStream = new GZipStream(responseStream, CompressionMode.Decompress); else if (httpWebResponse.ContentEncoding.ToLower().Contains("deflate")) responseStream = new DeflateStream(responseStream, CompressionMode.Decompress); MemoryStream memStream = new MemoryStream(); byte[] respBuffer = new byte[4096]; try { int bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length); while (bytesRead > 0) { memStream.Write(respBuffer, 0, bytesRead); bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length); } } finally { responseStream.Close(); } byte[] msg = memStream.ToArray(); context.Response.ContentLength64 = msg.Length; using (Stream strOut = context.Response.OutputStream) { strOut.Write(msg, 0, msg.Length); } } catch (Exception ex) { // Some error handling } }

con enchufes Esto es lo que tengo hasta ahora:

void ProcessRequest(object listenerContext) { HttpListenerContext context = (HttpListenerContext)listenerContext; Uri URL = new Uri(context.Request.RawUrl); string getString = string.Format("GET {0} HTTP/1.1/r/nHost: {1}/r/nAccept-Encoding: gzip/r/n/r/n", context.Request.Url.PathAndQuery, context.Request.UserHostName); Socket socket = null; string[] hostAndPort; if (context.Request.UserHostName.Contains(":")) { hostAndPort = context.Request.UserHostName.Split('':''); } else { hostAndPort = new string[] { context.Request.UserHostName, "80" }; } IPHostEntry ipAddress = Dns.GetHostEntry(hostAndPort[0]); IPEndPoint ip = new IPEndPoint(IPAddress.Parse(ipAddress.AddressList[0].ToString()), int.Parse(hostAndPort[1])); socket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socket.Connect(ip);

COMIENZO NUEVO CÓDIGO

Encoding ASCII = Encoding.ASCII; Byte[] byteGetString = ASCII.GetBytes(getString); Byte[] receiveByte = new Byte[256]; string response = string.Empty; socket.Send(byteGetString, byteGetString.Length, 0); Int32 bytes = socket.Receive(receiveByte, receiveByte.Length, 0); response += ASCII.GetString(receiveByte, 0, bytes); while (bytes > 0) { bytes = socket.Receive(receiveByte, receiveByte.Length, 0); strPage = strPage + ASCII.GetString(receiveByte, 0, bytes); } socket.Close(); string separator = "/r/n/r/n"; string header = strPage.Substring(0,strPage.IndexOf(separator)); string content = strPage.Remove(0, strPage.IndexOf(separator) + 4); byte[] byteResponse = ASCII.GetBytes(content); context.Response.ContentLength64 = byteResponse .Length; context.Response.OutputStream.Write(byteResponse , 0, byteResponse .Length); context.Response.OutputStream.Close();

FIN DE NUEVO CÓDIGO

Después de conectarme al zócalo, no sé cómo descomprimir la respuesta de Stream y enviar de vuelta a context.Response.OutputStream

Cualquier ayuda será apreciada. Gracias. Aclamaciones.

EDIT 2: con esta edición ahora parece estar funcionando bien (al igual que HttpWebRequest al menos). ¿Encuentra algún error aquí?

EDIT 3: Falsa alarma ... Todavía no puedo hacer que esto funcione

EDIT 4: Necesitaba agregar las siguientes líneas al código de Scott ... porque no siempre el primero en bytes de reponseStream es el número mágico de gzip. La secuencia parece ser: 0x0a (10), 0x1f (31), 0x8b (139). Los dos últimos son el número mágico de gzip. El primer número siempre fue antes en mis pruebas.

if (contentEncoding.Equals("gzip")) { int magicNumber = 0; while (magicNumber != 10) magicNumber = responseStream.ReadByte(); responseStream = new GZipStream(responseStream, CompressionMode.Decompress); }


Socket, por definición, es el bajo nivel para acceder a la red. Incluso puede usar protocolos de datagramas con un socket. En ese caso, una transmisión no tiene ningún sentido.

Si bien no estoy seguro de por qué estás haciendo lo que HttpWebRequest logra fácilmente, para leer / escribir datos en un socket, utilizas los métodos Enviar / Recibir. Si desea tener un acceso de flujo continuo a un socket TCP, debe usar las clases TcpClient / TcpListener que envuelven un socket y le proporcionan una secuencia de red.


También está la clase NetworkStream que toma un socket como parámetro. ;)


Aquí hay un código que funciona para mí.

using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Sockets; using System.Text; using System.IO.Compression; namespace HttpUsingSockets { public class Program { private static readonly Encoding DefaultEncoding = Encoding.ASCII; private static readonly byte[] LineTerminator = new byte[] { 13, 10 }; public static void Main(string[] args) { var host = ".com"; var url = "/questions/523930/sockets-in-c-how-to-get-the-response-stream"; IPHostEntry ipAddress = Dns.GetHostEntry(host); var ip = new IPEndPoint(ipAddress.AddressList[0], 80); using (var socket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp)) { socket.Connect(ip); using (var n = new NetworkStream(socket)) { SendRequest(n, new[] {"GET " + url + " HTTP/1.1", "Host: " + host, "Connection: Close", "Accept-Encoding: gzip"}); var headers = new Dictionary<string, string>(); while (true) { var line = ReadLine(n); if (line.Length == 0) { break; } int index = line.IndexOf('':''); headers.Add(line.Substring(0, index), line.Substring(index + 2)); } string contentEncoding; if (headers.TryGetValue("Content-Encoding", out contentEncoding)) { Stream responseStream = n; if (contentEncoding.Equals("gzip")) { responseStream = new GZipStream(responseStream, CompressionMode.Decompress); } else if (contentEncoding.Equals("deflate")) { responseStream = new DeflateStream(responseStream, CompressionMode.Decompress); } var memStream = new MemoryStream(); var respBuffer = new byte[4096]; try { int bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length); while (bytesRead > 0) { memStream.Write(respBuffer, 0, bytesRead); bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length); } } finally { responseStream.Close(); } var body = DefaultEncoding.GetString(memStream.ToArray()); Console.WriteLine(body); } else { while (true) { var line = ReadLine(n); if (line == null) { break; } Console.WriteLine(line); } } } } } static void SendRequest(Stream stream, IEnumerable<string> request) { foreach (var r in request) { var data = DefaultEncoding.GetBytes(r); stream.Write(data, 0, data.Length); stream.Write(LineTerminator, 0, 2); } stream.Write(LineTerminator, 0, 2); // Eat response var response = ReadLine(stream); } static string ReadLine(Stream stream) { var lineBuffer = new List<byte>(); while (true) { int b = stream.ReadByte(); if (b == -1) { return null; } if (b == 10) { break; } if (b != 13) { lineBuffer.Add((byte)b); } } return DefaultEncoding.GetString(lineBuffer.ToArray()); } } }

Puede sustituir esto por Socket / NetworkStream y ahorrar un poco de trabajo.

using (var client = new TcpClient(host, 80)) { using (var n = client.GetStream()) { } }