python-socket编程
五层网络模型
应用层
功能:文件传输,电子邮件,文件服务,数据传输
TCP/IP协议:HTTP,FTP,SMTP,DNS,TELNET,SSH
传输层
功能:提供端口对端口的接口
TCP/IP协议:TCP-UDP
网络层
功能:为数据包选择路由
TCP/IP协议:IP,ICMP
数据链路层
功能:传输有地址的帧,错误检测功能
TCP/IP协议:ARP
物理层
功能:物理媒体,光纤
TCP/IP协议:1000BASE-SX
每次的网络传输请求都是通过 应用层–->传输层–->网络层–->数据链路层–->物理层传递。
除了应用层,其他的层都由操作系统,物理设备完成,所以通过操作系统提供的接口socket直接走传输层(通过TCP链接,socket不属于网络协议,属于自己定义的协议)可以完成大部分不同协议的网络请求。
c/s实现通信
使用socket实现客户端与服务端的通信,偷一张图(socket的固定编程模式)
服务端代码:
1 | import socket |
客户端代码:
1 | import socket |
socket的编码模式基本上可以说是固定的,套用代码即可。
先运行服务端代码,再运行客户端代码:
客户端返回结果:
1 | shuke呼叫总部 |
服务端返回结果:
1 | 总部收到总部收到 |
这个就是固定的套路代码,如果想要让服务端一直接受客户端的请求的话,在这里修改代码即可:
1 | s.bind(('0.0.0.0',9999)) |
注意socket发送的内容必须要是bytes类型的(python3),这里说明一下:
1 | 对于bytes编码的数据来说 |
C/S端相互发消息
- 服务端发送代码
1
2
3
4
5
6
7
8
9
10
11
12import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('0.0.0.0',9999))
s.listen()
sock, addr = s.accept()
while 1:
inp = input('输入消息:')
sock.send(inp.encode('utf-8'))
data = sock.recv(1024)
print('接收消息:'+data.decode('utf-8')) - 客户端发送代码服务端返回结果:
1
2
3
4
5
6
7
8import socket
c = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
c.connect(('127.0.0.1',9999))
while 1:
data = c.recv(1024)
print('接收消息:'+data.decode('utf-8'))
inp = input('输入消息:')
c.send(inp.encode('utf-8'))客户端返回结果:1
2
3输入消息:我是你爸爸
接收消息:我是你爷爷
输入消息:1
2接收消息:我是你爸爸
输入消息:我是你爷爷多用户连接
从上面的代码中一个sock只能服务一个客户端,服务端只能服务一个对象,使用多线程即可完成一个服务端服务大量的客户端。
服务端代码:客户端代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18import socket
import threading
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('0.0.0.0',9999))
s.listen()
def handle_sock(sock,addr):
while 1:
inp = input('输入消息:')
sock.send(inp.encode('utf-8'))
data = sock.recv(1024)
print('接收消息:' + data.decode('utf-8'))
while 1:
sock, addr = s.accept()
clinent_thread = threading.Thread(target=handle_sock,args=(sock,addr))
clinent_thread.start()这个时候运行两个客户端发送请求一样可以被服务端获取到。1
2
3
4
5
6
7
8import socket
c = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
c.connect(('127.0.0.1',9999))
while 1:
data = c.recv(1024)
print('接收消息:'+data.decode('utf-8'))
inp = input('输入消息:')
c.send(inp.encode('utf-8'))
模拟HTTP请求
requests本质上调用urllib发起网络请求,urllib通过调用socket发起网络请求。模拟socket对HTTP请求就是对本质上进行重写编程。
具体实现看代码,其实很简单的,不多描述
1 | import socket |