MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Какой POST/GET запрос выполняется при нажатии кнопки на сайте?"
Answer 1171116
В WebBrowser, конечно, нет функционала для получения HTTP-запросов. Обычно для этих целей используют специальные программы, веб-отладчики. Но кое-какое решение можно состряпать и самостоятельно. Ключ к решению здесь - управляющий код SIO_RCVALL в WinSock, который позволяет прослушивать через сокет все IP-пакеты на сетевом интерфейсе. Основа решения описана здесь: https://ru.stackoverflow.com/a/1019378/240512, в данном ответе мы добавим, помимо заголовков запросов, прослушивание их содержимого:
using System; using System.IO; using System.Collections.Generic; using System.Text; using System.Windows; using System.Windows.Controls; using System.Threading; using System.Net; using System.Net.Sockets; using System.Net.NetworkInformation; namespace WpfTest { public partial class MainWindow : Window { string navigated_host = ""; //последний сайт, на который перешел WebBrowser IPAddress target_ip=null; //IP адрес последнего сервера, к которому обратился WebBrowser object sync = new object(); public MainWindow() { InitializeComponent(); webbrowser.Navigating += webbrowser_Navigating; var ips = GetIpAddresses(); foreach (IPAddress ip in ips) { Thread th = new Thread(ThreadProc); th.IsBackground = true; th.Start((object)ip); } } void TextBoxWriteLine(string s) { this.Dispatcher.Invoke(() => { textbox.Text += s + Environment.NewLine; }); } void webbrowser_Navigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e) { lock (sync) { navigated_host = e.Uri.Host; } } //Получает все локальные IP-адреса public static List<IPAddress> GetIpAddresses() { List<IPAddress> res = new List<IPAddress>(10); var ifs = NetworkInterface.GetAllNetworkInterfaces(); foreach (var interf in ifs) { var ipprop = interf.GetIPProperties(); if (ipprop == null) continue; var unicast = ipprop.UnicastAddresses; if (unicast == null) continue; //находим первый Unicast-адрес foreach (var addr in unicast) { if (addr.Address.AddressFamily != AddressFamily.InterNetwork) continue; res.Add(addr.Address); break; } } return res; } const byte PROTO_TCP = 6; public string ParseIpPacket(byte[] data, IPAddress src_ip) { ushort dummy; byte b; MemoryStream ms = new MemoryStream(data); BinaryReader br = new BinaryReader(ms); uint header_len; uint total_len; IPAddress src, dst; string host = ""; //parse IP packet header using (ms) using (br) { b = br.ReadByte(); byte ver = (byte)((b & (byte)0xF0) >> 4); //IP version if (ver != 4) { TextBoxWriteLine("Unsupported IP version: " + ver.ToString()); return null; } byte ihl = (byte)(b & (byte)0x0F);//header length header_len = ihl * 4u; b = br.ReadByte(); //packet length byte[] temp = new byte[2]; temp[1] = br.ReadByte(); temp[0] = br.ReadByte(); total_len = BitConverter.ToUInt16(temp, 0); dummy = br.ReadUInt16(); dummy = br.ReadUInt16(); byte ttl = br.ReadByte(); byte proto = br.ReadByte(); dummy = br.ReadUInt16(); //source IP temp = new byte[4]; temp[0] = br.ReadByte(); temp[1] = br.ReadByte(); temp[2] = br.ReadByte(); temp[3] = br.ReadByte(); src = new IPAddress(temp); //destination IP temp[0] = br.ReadByte(); temp[1] = br.ReadByte(); temp[2] = br.ReadByte(); temp[3] = br.ReadByte(); dst = new IPAddress(temp); if (proto != PROTO_TCP) return null; } //Parse TCP packet uint tcp_size = total_len - header_len; byte[] tcp_data = new byte[tcp_size]; Array.Copy(data, header_len, tcp_data, 0, tcp_size); ms = new MemoryStream(tcp_data); br = new BinaryReader(ms); byte tcp_header_size; uint http_size; using (ms) using (br) { var src_port = br.ReadUInt16(); var dst_port = br.ReadUInt16(); br.ReadUInt32(); br.ReadUInt32(); tcp_header_size = (byte)(br.ReadByte() >> 4); tcp_header_size *= 4; http_size = tcp_size - tcp_header_size; } byte[] http_data = new byte[http_size]; Array.Copy(tcp_data, tcp_header_size, http_data, 0, http_size); //Parse HTTP data string res = Encoding.UTF8.GetString(http_data); lock (this.sync) { //если IP-адрес соответствует сохраненному адресу сервера, возвращаем содержимое запроса if (dst.Equals(this.target_ip)) { return res; } } string[] arr = res.Split("\n\r".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if (arr.Length > 2 && arr[0].Contains("HTTP/")) { //найдем поле Host for (int i = 1; i < arr.Length; i++) { if (arr[i].StartsWith("Host: ")) { host = arr[i].Replace("Host: ", ""); break; } } if (host == "") { //пытаемся получить имя узла из обратного DNS try { host = Dns.GetHostEntry(dst).HostName; } catch (SocketException) { host = ""; } } lock (sync) { if (host == navigated_host) { //если поле host соответствует сайту, на который перешел веб-браузер, сохраняем IP сервера this.target_ip = dst; //возвращаем содержимое запроса return res; } } } return null; } public void ThreadProc(object args) { var mainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP); IPAddress ipaddr = (IPAddress)args; //начинаем прослушивание пакетов на интерфейсе... mainSocket.Bind(new IPEndPoint(ipaddr, 0)); mainSocket.SetSocketOption(SocketOptionLevel.IP, //Applies only to IP packets SocketOptionName.HeaderIncluded, //Set the include header true); //option to true byte[] byTrue = new byte[4] { 1, 0, 0, 0 }; byte[] byOut = new byte[4]; //Socket.IOControl is analogous to the WSAIoctl method of Winsock 2 mainSocket.IOControl(IOControlCode.ReceiveAll, //SIO_RCVALL of Winsock byTrue, byOut); byte[] buffer = new byte[1024 * 20]; int res; while (true) { try { res = mainSocket.Receive(buffer); var result = ParseIpPacket(buffer, ipaddr); if (result != null) { TextBoxWriteLine(result); } } catch (Exception ex) { if (ex.GetType() != typeof(System.Threading.Tasks.TaskCanceledException)) { TextBoxWriteLine(ex.ToString()); } } } } private void Button1_Click(object sender, RoutedEventArgs e) { webbrowser.Navigate("http://example.com/"); } private void Button_Click(object sender, RoutedEventArgs e) { this.Close(); } } }
Ограничения решения:
- Работает только с IPv4-интерфейсами
- Работает только протоколом HTTP (не HTTPS)
- Для запуска требуются права администратора
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.