[TOC] >[success] # 简单入门 >[danger] ##### 网址的组成 ~~~ 1.协议 http,https 其中 https 是http加密协议 2.主机 baidu.com kancloud.cn 之类的网址 3.端口 HTTP 协议默认80, 因此一般不用填写 4.路径 主机后面用 [/] 分割的就是路径 ~~~ >[danger] ##### ip和域名 ~~~ 1.电脑通信是靠IP地址,ip由于繁琐不容易记住,诞生了域名 2.电脑想DNS 服务器查新域名对应IP 3.win 查询对应ip 指令ping 主机名 ~~~ ![](https://box.kancloud.cn/f07cc7317289a03016594a08b30f4dcd_554x211.png) >[danger] ##### 什么是端口 ~~~ 1.广为流传的比喻,ip相当于你写信的地址,端口相当于收信人 2.端口是一个16位数字,范围在0-65535 也就是2**16 ~~~ >[danger] ##### HTTP协议 ~~~ 1.一种传输协议,双方都要遵守规范 2.由于收发的是文本信息,所以叫超文本传输协议 3.浏览器(客户端)按照规定的格式发送文本数据请求到服务器 4.服务器去响应请求,按照规定格式返回文本数据到浏览器 5.浏览器去解析处理得到的数据 ~~~ >[danger] ##### HTTP请求和响应 ~~~ 1.请求行或者响应行 2.Header 3.\r\n\r\n ,连续两个回车符,用来分割Header 和Body 4.Body ~~~ <hr/> * 解释说明 请求 -- request ![](https://box.kancloud.cn/8bebf91980d56bc707ec4f41482e9cd7_339x54.png) ~~~ 原始数据: 1.GET / HTTP/1.1\r\nhost:www.baidu.com\r\n\r\n 打印数据: 1.请求行: GET / HTTP/1.1 2.请求头: Host: www.baidu.com 解释: 1.GET 是请求方式 2./是请求路径 3.HTTP/1.1 中,1.1是版本号 ~~~ <hr/> * 解释说明 响应 -- respnse ![](https://box.kancloud.cn/6e46441acf678f57d078a411ed8beedc_274x72.png) ~~~ 1.响应行:HTTP/1.1 200 OK 2.响应头:Content-Length: 218 Content-Type: text/html; charset=UTF-8 ~~~ >[success] # 利用socket 客户端和服务器 >[danger] ##### 客户端 client.py ~~~ 1.创建一个socket对象 2.创建主机和域名 3.连接主机 4.发送 HTTP 请求给服务器,发送要以bytes 字节类型 5.服务器会响应数据,响应的数据也是bytes 字节类型 6.如果页面 有一些src 便签属性的时候,客户端会接着在去请求服务器,获取 ~~~ ~~~ import socket # 创建一个 socket 对象 # 参数 socket.AF_INET 表示是 ipv4 协议 # 参数 socket.SOCK_STREAM 表示是 tcp 协议 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 这两个其实是默认值, 所以你可以不写, 如下 # s = socket.socket() # 如果是https 协议 # s = ssl.wrap_socket(socket.socket()) # 主机(域名或者ip)和端口 host = 'g.cn' port = 80 # 用 connect 函数连接上主机, 参数是一个 tuple s.connect((host, port)) # 连接上后, 可以通过这个函数得到本机的 ip 和端口 ip, port = s.getsockname() print('本机 ip 和 port {} {}'.format(ip, port)) # 构造一个 HTTP 请求 http_request = 'GET / HTTP/1.1\r\nhost:{}\r\n\r\n'.format(host) # 发送 HTTP 请求给服务器 # send 函数只接受 bytes 作为参数 # str.encode 把 str 转换为 bytes, 编码是 utf-8 request = http_request.encode('utf-8') print('请求', request) s.send(request) # 接受服务器的响应数据 # 参数是长度, 这里为 1023 字节 # 所以这里如果服务器返回的数据中超过 1023 的部分你就得不到了 response = s.recv(1023) # 输出响应的数据, bytes 类型 print('响应', response) # 转成 str 再输出 print('响应的 str 格式', response.decode('utf-8')) ~~~ ![](https://box.kancloud.cn/becee0b1abac94ba1066566fe72bda28_718x343.png) >[danger] 服务端-- server.py ~~~ 1.创建一个服务器host,和端口,不填默认本地host 2.把host 和端口绑定 3.循环监听,当有请求的时候执行s.accept(),没有的时候就卡住 4.构造一个字节按照响应的格式 返回个客户端 ~~~ ~~~ import socket # 运行这个程序后, 浏览器打开 localhost:2000 就能访问了 # 服务器的 host 为空字符串, 表示接受任意 ip 地址的连接 # post 是端口, 这里设置为 2000, 随便选的一个数字 host = '' port = 2000 # s 是一个 socket 实例 s = socket.socket() # s.bind 用于绑定 # 注意 bind 函数的参数是一个 tuple,绑定服务器和端口 s.bind((host, port)) # 用一个无限循环来处理请求 while True: # 套路, 先要 s.listen 开始监听 s.listen(5) # 当有客户端过来连接的时候, s.accept 函数就会返回 2 个值 # 分别是 连接 和 客户端 ip 地址 connection, address = s.accept() # recv 可以接收客户端发送过来的数据 # 参数是要接收的字节数 # 返回值是一个 bytes 类型 # 取出所有数据 buffer_size = 1000 r = b'' while True: request = connection.recv(buffer_size) r +=request if len(request)<buffer_size: break # bytes 类型调用 decode('utf-8') 来转成一个字符串(str) print('ip and request, {}\n{}'.format(address, request.decode('utf-8'))) # b'' 表示这是一个 bytes 对象,构造的响应信息格式 response = b'HTTP/1.1 200 OK\r\n\r\n<h1>Hello World!</h1>' # 用 sendall 发送给客户端 connection.sendall(response) # 发送完毕后, 关闭本次连接 connection.close() ~~~ >[success] # 解码和编码 ![](https://box.kancloud.cn/37c55dba92f9b7a1ae5f7d5572b23879_324x262.png)