1. 基础知识
1.1 什么是协议
我理解的协议是数据发送方和接收方相互指定的规则。
1.2 有哪些协议
| 常用协议 |
---|
应用层 | HTTP协议,FTP协议 | 传输层 | TCP协议、UDP协议 | 网络层 | IP协议、ICMP协议、IGMP协议 | 网络接口层 | ARP协议、RARP协议 |
TCP传输控制协议(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。 UDP用户数据报协议(User Datagram Protocol)是OSl参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。 HTTP超文本传输协议(Hyper Text Transfer Protocol)是互联网上应用最为广泛的一种网络协议。
1.3 分层模型
TCP/IP模型不是说只有TCP协议和IP协议,在传输层除了TCP外,还可以是UDP协议,此外还包含网络接口层和应用层。
1.4 什么是套接字Socket编程
我们编写发出信息的程序和接收信息的程序,并不需要知道信息传输的所有细节,比如 中间经过哪些路由器,路由器之间又是如何传输的。 我们作为程序员,只要知道,我们的程序如何把所要发送的信息交给 ‘收件人’, 如何从 ‘送件人’ 手中获取信息。 那么和我们应用程序直接打交道的 ‘收件人’ 和 ‘送件人’ 到底是谁? 就是操作系统 提供的socket编程接口。
1.5 套接字通信过程
流式套接字(TCP) 数据报套接字(UDP)
2. Python实现
2.1 socket
TCP 服务端程序 server.py
from socket import *
IP = ''
PORT = 50000
BUFLEN = 512
listenSocket = socket(AF_INET, SOCK_STREAM)
listenSocket.bind((IP, PORT))
listenSocket.listen(8)
print(f'服务端启动成功,在{PORT}端口等待客户端连接...')
dataSocket, addr = listenSocket.accept()
print('接受一个客户端连接:', addr)
while True:
recved = dataSocket.recv(BUFLEN)
if not recved:
break
info = recved.decode()
print(f'收到对方信息: {info}')
dataSocket.send(f'服务端接收到了信息 {info}'.encode())
dataSocket.close()
listenSocket.close()
下面是TCP 客户端程序 client.py
from socket import *
IP = '127.0.0.1'
SERVER_PORT = 50000
BUFLEN = 1024
dataSocket = socket(AF_INET, SOCK_STREAM)
dataSocket.connect((IP, SERVER_PORT))
while True:
toSend = input('>>> ')
if toSend =='exit':
break
dataSocket.send(toSend.encode())
recved = dataSocket.recv(BUFLEN)
if not recved:
break
print(recved.decode())
dataSocket.close()
2.2 socketserver
socketserver本质是基于socket进行的一个封装,将多线程并发功能集成到一个新的模块里,就叫socketserver;
在原来的socket编程中,有按一定的顺序进行绑定、监听什么的,而socketserver帮助你把这些事情一并完成,你只需要提高IP地址、端口号以及选择适当的协议类型。 关于socketserver模块中各个类,可参考博文Python3之源码解读socketserver工作流程 以下代码摘自:并发编程之socketserver模块(未尝试) 服务器端
import socketserver
class MyTCPhandle(socketserver.BaseRequestHandler):
def handle(self):
while True:
try:
data = self.request.recv(1024)
self.request.send(data.upper())
except Exception:
break
self.request.close()
if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyTCPhandle)
server.allow_reuse_address = True
server.serve_forever()
客户端
from socket import *
client = socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))
while True:
cmd = input('>>:').strip()
if not cmd:continue
client.send(cmd.encode('utf-8'))
data = client.recv(1024)
print('接受的是:%s'%data.decode('utf-8'))
client.close()
官方说明库:socketserver — 用于网络服务器的框架?
2.3 http.server
由1.4节中可以知道,socket编程是位于协议和进程之间,主要对象是网络层中的TCP协议,而http.server作用对象则是应用层的http协议。(可能描述不准确)
http.server 使用 socketserver 中的一些类来创建用于实现 HTTP 服务器的基类(基于TCPServer)。HTTPServer 可以直接拿来用,而 BaseHTTPRequestHandler 的目的则是提供一个可供扩展的基础,以便处理各项协议 ( GET,POST 等)。
推荐阅读 Python中的http.server初步使用教程与学习心得 Python3搭建网页 官方文档 3. Python3: 简易的 HTTP 服务器 - http.server http.server总结 说白了就是利用http.server模块可以创建一个网址,在同一局域网的用户可以查看网址的信息。 为了能够生成相应的网页,必须先遵循相应的HTTP协议,该协议已经封装在http.server的某些类中,因此你需要首先遵循官方文档的写法,创建成功基本的连接。 接下来则需要在网页中添加东西,涉及到"do_GET()",这里也涉及到了HTTP协议相关的内容。
在do_GET()中,如果请求被映射到目录,则会依次检查该目录是否存在 index.html 或 index.htm 文件。若存在则返回文件内容;否则会调用 list_directory() 方法生成目录列表。本方法将利用 os.listdir() 扫描目录,如果 listdir() 失败,则返回 404 出错应答。
在do_GET()函数书写中,设计相应的要求:
self.send_response(200)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.end_headers()
self.wfile.write("Hello World\n".encode("utf-8"))
参考链接
socket编程
|