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

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)步循环开始。

用图表示以上过程:

图1

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

  • 无连接:

服务器与浏览器之间的一次连接只处理一个http请求,请求处理结束后,连接断开。下一次请求再重新建立连接。

  • 无状态:

服务器不会保存浏览器信息。也就是说,在服务器端,第一次http请求处理的结果不会保留到第二次请求。如果第二次请求处理时,需要用到第一次请求处理的结果,浏览器在第二次请求时,必须将第一次处理结果重新传回给Web服务器(比如使用cookie)。

关于“协议”:

这个话题有点大,不是我能掌控得了的。不过对于今天这篇文章,我还是尽最大可能说一点。计算机中协议范畴广泛,单就网络通信中的协议,就不计其数,OSI七层中每层都很多种协议。那么协议到底本质上是个什么东西呢?单就通信中的协议来讲,协议的本质其实就是一种数据结构,类似代码中的结构体,说得再底层一点,就是一个字节流,规定好了第一个字节代表什么、第二个字节代表什么等等。

协议的作用跟我们平时所说的“契约”、“约定”类似,一个团队合作的任务,合作各方必须同时遵守事先的约定,最后工作才能正常进行下去。网络通信中也一样,通信双方收/发数据时必须按照实现规定好了的结构去发送/接收,一方不遵守该规范,通信就不能成功。这里说的结构规范其实就是“协议”。协议有以下作用:

  • 既然是规范,那么按照规范做事,自己做的别人更容易理解,便于交流;
  • 将规范写成文档,提供给其他人,方便后期他人扩展。因为只要知道了通信规范,那么很容易就可以编写出扩展模块与原有系统协调工作。
  • 计算机网络通信中,有些因素决定了我们必须按照规定的格式收发数据,比如TCP通信中,由于数据是按照“流”式传输的,如果我们事先不定义数据传输规范,那么很难判断TCP传输的数据边界。

就网络通信协议来讲,应用层协议与我们程序开发最为密切(至少对我们使用c#、java的人来讲),其他向tcp、udp等传输层协议几乎用不到。我们开发的通信程序,必须遵守实现定义好了的应用层协议,比如浏览器和Web服务器都遵守了HTTP应用层协议,只有这样,它们才能正常交互。倘若我们自己开发一个程序,正确地遵守了HTTP协议,那么我们的程序也能够像chrome、IE等浏览器一样,去访问Web服务器。

文章末尾有一个使用socket模拟浏览器请求Web服务器的demo,实现的功能我们完全可以使用类似WebClient、WebRequest等类型去实现。demo功能如下:

  • 使用Socket连接Web服务器(任意);
  • 按照HTTP协议格式发送HTTP请求(使用Socket.Send方法);
  • 按照HTTP协议格式解析Web服务器返回的数据(其实就显示在了UI界面)

(开发这样的程序需要我们充分熟悉socket编程、HTTP协议格式)

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

  /// <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, , * , SocketFlags.None, new AsyncCallback(OnReceive), socket);
}

下面是效果图:

图2

源码下载:http://files.cnblogs.com/xiaozhi_5638/socket_browser.rar

C#中使用Socket请求Web服务器过程的更多相关文章

  1. 详谈socket请求Web服务器过程

    最开始我们需要明白一件事情,因为这是这篇文章的前提: HTTP协议只是一个应用层协议,它底层是通过TCP进行传输数据的.因此,浏览器访问Web服务器的过程必须先有“连接建立”的发生. 而有人或许会问: ...

  2. 详谈socket请求Web服务器过程(转)

    最开始我们需要明白一件事情,因为这是这篇文章的前提: HTTP协议只是一个应用层协议,它底层是通过TCP进行传输数据的.因此,浏览器访问Web服务器的过程必须先有“连接建立”的发生. 而有人或许会问: ...

  3. 【网络开发】详谈socket请求Web服务器过程

    最开始我们需要明白一件事情,因为这是这篇文章的前提: HTTP协议只是一个应用层协议,它底层是通过TCP进行传输数据的.因此,浏览器访问Web服务器的过程必须先有"连接建立"的发生 ...

  4. TCP/IP协议学习(七) 基于C# Socket的Web服务器---动态通讯实现

    目录 (1).基于Ajax的前端实现 (2).Web服务器后端处理 一个完整的web服务器,不仅需要满足用户端对于图片.文档等资源的需求:还能够对于用户端的动态请求,返回指定程序生成的数据.支持动态请 ...

  5. TCP/IP协议学习(四) 基于C# Socket的Web服务器---静态资源处理

    目录 1. C# Socket通讯 2. HTTP 解析引擎 3. 资源读取和返回 4. 服务器测试和代码下载 Web服务器是Web资源的宿主,它需要处理用户端浏览器的请求,并指定对应的Web资源返回 ...

  6. 访问虚拟机中的架设的Web服务器

    环境: 1.虚拟机中安装了CentOS,虚拟机使用NAT的方式 2.在CentOS中安装了APACHE 并且使用 http://127.0.0.1可以正常访问,通过ifconfig查到IP地址是 19 ...

  7. 第一篇 先用socket模拟web服务器

    一.用socket来模拟网站访问 socket为python2.7 #!/usr/bin/env python # -*- coding:utf-8 -*- import socket def han ...

  8. Socket模拟Web服务器

    效果如下: 源码下载地址:https://github.com/doyoulaikeme/DotNetSample/tree/master/DotNetSample3/SocketWebServer

  9. C#中使用Socket实现简单Web服务器

    上一篇博客中介绍了怎样使用socket访问web服务器.关键有两个: 熟悉Socket编程: 熟悉HTTP协议. 上一篇主要是通过socket来模拟浏览器向(任何)Web服务器发送(HTTP)请求,重 ...

随机推荐

  1. MIT 6.828 JOS学习笔记12 Exercise 1.9

    Lab 1中Exercise 9的解答报告 Exercise 1.9: 判断一下操作系统内核是从哪条指令开始初始化它的堆栈空间的,以及这个堆栈坐落在内存的哪个地方?内核是如何给它的堆栈保留一块内存空间 ...

  2. 进击的Python【第二章】:Python基础(二)

    Python基础(二) 本章内容 数据类型 数据运算 列表与元组的基本操作 字典的基本操作 字符编码与转码 模块初探 练习:购物车程序 一.数据类型 Python有五个标准的数据类型: Numbers ...

  3. Python 判断变量的类型

    这里有两种方法.type 和isinstance import types aaa = 0 print type(aaa) if type(aaa) is types.IntType: print & ...

  4. 我理想中的父母(The Ideal Parents In My Heart)

    Parents are the first teachers in children's life, and people all know the great importance exactly ...

  5. 矩阵快速幂 HDU 4565 So Easy!(简单?才怪!)

    题目链接 题意: 思路: 直接拿别人的图,自己写太麻烦了~ 然后就可以用矩阵快速幂套模板求递推式啦~ 另外: 这题想不到或者不会矩阵快速幂,根本没法做,还是2013年长沙邀请赛水题,也是2008年Go ...

  6. mac rvm升级ruby

    rvm是什么?为什么要安装rvm呢,因为rvm可以让你拥有多个版本的Ruby,并且可以在多个版本之间自由切换.第一步:安装rvm $ curl -L get.rvm.io | bash -s stab ...

  7. EditText限制小数点前后位数

    在EditText输入数字的时候,通常我们需要限制小数点前后位数.比如金额输入一般我们需要限制小数点后面最多2位.我们可以通过 TextWatcher 实现. public class MyWatch ...

  8. volatile不能保证原子性

    1.看图自己体会 2.体会不了就给你个小程序 package cs.util; public class VolatileDemo { private volatile int count =0; p ...

  9. BZOJ2506: calc

    Description            给一个长度为n的非负整数序列A1,A2,…,An.现有m个询问,每次询问给出l,r,p,k,问满足l<=i<=r且Ai mod p = k的值 ...

  10. 让/etc/profile文件修改后立即生效

    方法1: 让/etc/profile文件修改后立即生效 ,可以使用如下命令: # .  /etc/profile 注意: . 和 /etc/profile 有空格 方法2: 让/etc/profile ...