首页 > 编程语言 >C#中使用Socket请求Web服务器过程

C#中使用Socket请求Web服务器过程

时间:2024-10-14 16:32:47浏览次数:6  
标签:Web 浏览器 Socket C# socket 请求 string

最开始我们需要明白一件事情,因为这是这篇文章的前提:

HTTP协议只是一个应用层协议,它底层是通过TCP进行传输数据的。因此,浏览器访问Web服务器的过程必须先有“连接建立”的发生。

而有人或许会问:众所周知,HTTP协议有两大特性,一个是“无连接”性,一个是“无状态”性。这里的“无连接”岂不是跟上面的说法有冲突?其实这里并没有矛盾,
只是人们对“连接”这个词的理解有差异。首先我们来看一下浏览器向Web服务器发出Http请求以及Web服务器给浏览器回复的过程:
  1. 浏览器创建Socket,按给定IP(域名)和端口(默认为80)连接服务器。比如使用类似Socket.Connect()、Socket.BeginConnect()等方法;
  2. 连接成功后,浏览器依据HTTP协议规范(关于协议,后面有讲到),向Web服务器发送请求数据。比如“请求行”、“请求头标”以及“请求数据”等,这里可能使用类似Socket.Send()、Socket.BeginSend()等方法。【关于HTTP协议中的请求行、请求头标等请参见http://www.cnblogs.com/riky/archive/2007/04/09/705848.html
  3. 浏览器等待服务器处理并返回数据;
  4. Web服务器端使用Socket.Accept()、Socket.BeginAccept()等方法侦听到浏览器的连接后,便开始接收浏览器发送的数据。接收到请求数据后,依据HTTP协议规范解析数据,然后处理,最终将处理结果(如html文档)发回给浏览器,这里可能用到类似Socket.Send()、Socket.BeginSend()等方法;
  5. Web服务器发送完处理结果后,关闭Socket;
  6. 浏览器接收Web服务器发回的数据(如html),将其显示在浏览器UI界面。关闭socket;
  7. 一次“浏览器到Web服务器”的http请求结束;
  8. 下一次浏览器需要请求Web服务器,跳转到第1)步循环开始。

如上图所示。浏览器向Web服务器发送http请求之前,需要先建立连接。没错,它们间建立连接的过程跟我们平时开发socket程序类似。由此可知,
HTTP协议的“无连接”特性并不是指:浏览器与Web服务器进行数据交换时,不需要建立连接。那么“无连接”特性到底指什么呢?我们再看图1会发现,
浏览器每次请求完毕后都会与服务器处于“断开”状态,下一次请求时再重新与服务器建立连接。HTTP的无连接特性恰恰就是指浏览器的每次请求都必须重新与服务器建立连接,
正常情况下,浏览器不会与Web服务器保持长时间的连接状态。现将HTTP协议的两大特性归结如下:

 

 以下是发送HTTP请求的代码:

  /// <summary>
 2         /// 发送请求
 3         /// </summary>
 4         /// <param name="socket"></param>
 5         private void SendRequest(Socket socket)
 6         {
 7             string h1 = "GET " + _path + " HTTP/1.1\r\n";
 8             string h2 = "Accept: */*\r\n";
 9             string h3 = "Accept-Language: zh-cn\r\n";
10             string h4 = "Host: " + _host + "\r\n";
11             string h5 = "User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36\r\n";
12             string h7 = "Connection: close\r\n\r\n";
13 
14             byte[] send_buffer = Encoding.UTF8.GetBytes(h1 + h2 + h3 + h4 + h5 + h7);
15             socket.Send(send_buffer);
16             Print("请求发送完毕,等待Web Server回复...");
17             socket.BeginReceive(_buffer, 0, 640 * 1024, SocketFlags.None, new AsyncCallback(OnReceive), socket);
18         }

源码下载:https://files.cnblogs.com/xiaozhi_5638/socket_browser.rar
作者:周见智
出处:http://www.cnblogs.com/xiaozhi_5638/
首发公众号,扫描二维码关注公众号,分享原创计算机视觉/深度学习/算法落地相关文章
来源:https://www.cnblogs.com/xiaozhi_5638/p/3912668.html

 

public partial class Form1 : Form
    {
        Socket _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  //客户端socket
        byte[] _buffer = new byte[1024 * 640];  //接收缓冲区
        IPAddress _ip;  //当前请求主机IP
        int _port;  //当前请求主机Port
        string _path;  //当前请求url(除去主机部分)
        string _host; //当前请求url(主机部分)

        bool _isBusy = false;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
        /// <summary>
        /// 访问
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            if (_isBusy)
                return;
            if (textBox2.Text != "")
            {
                _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _isBusy = true;
                Uri u = new Uri(textBox2.Text);
                _ip = Dns.GetHostByName(u.Host).AddressList[0];
                _port = u.Port;
                _path = u.AbsolutePath;
                _host = u.Authority;

                Print("开始连接Web Server...");
                Print("Web Server信息:【" + "IP:" + _ip.ToString() + "     端口:" + _port + "】");

                _socket.BeginConnect(new IPEndPoint(_ip, _port), new AsyncCallback(OnConnect), _socket);  //使用socket连接web server
            }
        }
        /// <summary>
        /// 异步连接 回调
        /// </summary>
        /// <param name="ar"></param>
        private void OnConnect(IAsyncResult ar)
        {
            Socket socket = ar.AsyncState as Socket;
            try
            {
                socket.EndConnect(ar);
                Print("连接Web Server完成, 本地socket端口:"+ (_socket.LocalEndPoint as IPEndPoint).Port);
                Print("开始向Web Server请求数据...");
                SendRequest(socket);
            }
            catch
            {
                Print("连接Web Server失败!");
                _isBusy = false;
            }
        }
        /// <summary>
        /// 异步接收数据 回调
        /// </summary>
        /// <param name="ar"></param>
        private void OnReceive(IAsyncResult ar)
        {
            Socket socket = ar.AsyncState as Socket;
            try
            {
                int real_recv = socket.EndReceive(ar);  
                string recv_str = Encoding.UTF8.GetString(_buffer, 0, real_recv); //第一次接收数据
                while ((real_recv = socket.Receive(_buffer)) != 0)  //循环接收剩余数据
                {
                    recv_str += Encoding.UTF8.GetString(_buffer, 0, real_recv);
                }
                Print("收到Web Server的回复:");
                Print("\r\n"+recv_str);  //输出到界面
            }
            catch
            {

            }
            finally
            {
                _isBusy = false;
                _socket.Close();
            }
        }

        /// <summary>
        /// 发送请求
        /// </summary>
        /// <param name="socket"></param>
        private void SendRequest(Socket socket)
        {
            string h1 = "GET" + _path + " HTTP/1.1\r\n";
            string h2 = "Accept: */*\r\n";
            string h3 = "Accept-Language: zh-cn\r\n";
            string h4 = "Host: " + _host + "\r\n";
            string h5 = "User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36\r\n";
            string h7 = "Connection: close\r\n\r\n";

            byte[] send_buffer = Encoding.UTF8.GetBytes(h1 + h2 + h3 + h4 + h5 + h7);
            socket.Send(send_buffer);
            Print("请求发送完毕,等待Web Server回复...");
            socket.BeginReceive(_buffer, 0, 640 * 1024, SocketFlags.None, new AsyncCallback(OnReceive), socket);
        }

        /// <summary>
        /// 输出信息
        /// </summary>
        /// <param name="info"></param>
        private void Print(string info)
        {
            if (this.InvokeRequired)
            {
                this.Invoke((Action)delegate()
                {
                    DateTime now = DateTime.Now;
                    string time_str = now.ToString("hh:mm:ss");
                    textBox1.AppendText(time_str + " " + info + "\r\n");
                });
            }
            else
            {
                DateTime now = DateTime.Now;
                string time_str = now.ToString("hh:mm:ss");
                textBox1.AppendText(time_str + " " + info + "\r\n");
            }
        }
    }

 

标签:Web,浏览器,Socket,C#,socket,请求,string
From: https://www.cnblogs.com/ywtssydm/p/15887173.html

相关文章

  • pyaudio无法使用sudo执行:OSError: [Errno -9996] Invalid input device (no default o
    项目背景在树莓派上通过语音控制ws2812b灯带,使用 pyaudio 作为语音输入,使用 rpi_ws281x 控制灯带的颜色。问题描述目前出现的问题是由于rpi_ws281x使用PWM引脚,需要使用sudo来执行,但是pyaudio使用sudo执行时会报错:OSError:[Errno-9996]Invalidinputdevice(no......
  • SLM883x系列SLM8834两个零漂移可设置和稳定TEC温度 超紧凑高效率高精度TEC控制器
    SLM883x系列SLM8834是集成了双路功率调节器的单片TEC控制器。内部带有一个线性功率级、一个脉宽调制(PWM)功率级和两个零漂移、轨对轨运算放大器。线性功率级与PWM功率级同时工作,以控制H桥配置中的内部功率级的双向输出。通过测量热传感器反馈电压并使用集成运算放大器作为PID环......
  • SecureNN
    SecureNNSecureNN是SecureML与ABY后面的工作。Context在基于安全多方计算的隐私保护机器学习(PrivacyPreservingMachineLearning,PPML)语境下,最先开始考虑的神经网络便是CNN,这类网络简单,但是效果很好。SecureML与ABY3是两个较早的工作,并向我们展示了要实现CNN的PPML工作,需要关......
  • 如何在mkdocs-material文档主题下设置多版本文档系统?
    引言前一段时间,参与了PaddleOCR开源项目的文档站点搭建工作,基于mkdocs工具,采用mkdocs-material主题,基于GithubPages来搭建整个文档站点。目前该站点已经搭建完毕,支持多语言、文档搜索等诸多功能。最近得知,PaddleOCR文档站点需要支持多版本文档功能。这个需求是可以实现的,因为......
  • csp-s模拟11
    E题面最暴力的做法,枚举连续段长度\(i\),然后暴力搜索,复杂度\(O(n^3)\)点击查看代码#include<bits/stdc++.h>#definespeed()ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);#definelllonglong#definepbpush_back#defineullunsignedlonglong#define......
  • 实验4-2-3-for 验证“哥德巴赫猜想C++解法
    #include<iostream>#include<cmath>boolvia(longlongi);usingnamespacestd;intmain(){  longlongn=0,i=3,p=0,q=0,a=0,b=0;  cin>>n;  if(n>4)  {    for(i=3;i<n/2;i+=2)    {......
  • 螺旋方阵C++解法
    #include<iostream>#include<vector>usingnamespacestd;#include<iomanip>intn;intmain(){   cin>>n;   vector<vector<int>>arr(n,vector<int>(n,0));   intx=0,y=0,s=1;   while(s<=n*......
  • 网页内容获取:Scala自动化脚本的实现
    对于开发者和数据科学家来说,自动化获取网页内容是一个常见的需求。Scala,作为一种多范式编程语言,以其强大的函数式编程特性和并发处理能力,成为了编写高效自动化脚本的理想选择。本文将介绍如何使用Scala结合SeleniumWebDriver来自动化获取网页内容。为什么选择Scala?Scala......
  • 物联网CC2530按键单双击分别控制两灯
    (1)确定思路单击和双击的效果分别是怎样的(此文章采用简单的延时函数不涉及中断)。首先可以定义一个普通延时delay和一个标志位count变量,这里需有个延时阈值咱们直接可以宏定义B值(这里需要注意宏定义的值一定要大一些否则双击效果不会触发)。(2)在按下按键等待松开后,让变量count自增去与......
  • [ARC065E] へんなコンパス
    模拟赛题,简单题。首先选择的两点之间距离永远不变,设为\(d\)。对于一个确定的点\(x\),只要它能出现在一个对子里,其周围距离它为\(d\)的点都可以出现在对子里。也就是我们只需要考虑每个点周围距离为\(d\)的点数量以及是否能到达。暴力的思维是直接把四个平面拆开做cdq,数......