工作中接触到Socket编程,学习其基础知识并做记录,方便后续查阅。
直接开刀:python3.6.8+VScode
1、先看网文:(真香)
https://keelii.com/2018/09/24/socket-programming-in-python/
https://gist.github.com/kevinkindom/108ffd675cb9253f8f71
2、虽然上面解释得很清楚,但还需要结合以往的知识,换自己话来理解,避免形成知识孤岛:(如下图片均来源网络)
2.1、Socket是干什么用的?
先复习一下TCP/IP分层,再看看socket的抽象
在操作系统结构上看,socket涵盖了传输层协议、网络层和接口层,对于上层应用,屏蔽了TCP/IP网络层以下的网络细节;对于操作系统的用户空间提供网络抽象。
2.2、那Socket是怎么实现的?
先看Socket原语如下图,分两部分理解:
服务端:建立socket对象、绑定端口(默认80)、进行端口监听、接受三次握手、收到客户端数据、返回响应数据、收到断开连接、断开socket
客户端:建立socket对象、发起三次握手请求、发送请求数据、收到返回内容、断开socket
2.3、对于python而言,主要的用到的 Socket API 函数和方法有下面这些:(和原语一模一样)
socket()
bind()
listen()
accept()
connect()
connect_ex()
send()
recv()
close()
3、动手撸码加深印象:
服务端:server.py
import socket
import datetime
HOST = '0.0.0.0'
PORT = 9876 # 端口号是int类型,不需要引号
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # AF_INET 指明 IPV4, SOCK_STREAM 指明 TCP
s.bind((HOST,PORT)) # 绑定IP和端口
s.listen(5) # 监听间隔
while True:
conn,addr = s.accept() # 接收TCP链接,并返回新的socket对象
print('Client %s connected!' % str(addr))
dt = datetime.datetime.now()
msg = 'Current time is ' + str(dt)
conn.send(msg.encode()) # 向客户端发送当前时间
print('Sent: %s' % msg)
conn.close # 关闭链接
客户端:client.py
import socket
HOST = '127.0.0.1'
PORT = 9876
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
print('Connect %s:%s OK' % (HOST,PORT))
data = s.recv(1024)
print('Received: %s' % data)
s.close()
运行结果:
异常处理:TypeError: a bytes-like object is required, not 'str'
conn.send(msg.encode()),这里python3和Python2在套接字返回值解码上有区别。
- str通过encode()方法可以编码为指定的bytes
- 反过来,从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法