学习此章节知识前,请确保自己拥有网络基础知识的储备!
一、socket
1.1、何为socket?
socket即套接字,应用程序通常使用“套接字”向网络另一端发起请求或响应请求,以此实现计算机之间或者同一台计算机的进程间通信!socket是一组接口,它把TCP/IP协议簇封装在socket接口后面,使得我们能够非常方便地进行编写网络相关的应用程序!
1.1.1、AF_UNIX
Unix和Linux都是一切皆文件,套接字均基于文件系统实现数据调度;它只能在同一台机器上不同进程之间使用!
1.1.2、AF_INET
基于网络类型的套接字,因此可跨主机通信,这也是我们学习的重点!
1.2、为何用socket?
为能进行跨主机间进程通信!
1.3、如何用socket?
先来模拟一下场景:sanxi跟chrystal进行语音通话,sanxi先拨号,chrystal听到响铃接起电话;通话连接建立成功,开始交流;交流结束,挂断电话结束对话!
Python提供了一个模块,就叫socket!下面展示一下socket基本语法:
import socket
socket.socket(socket_family,socket_type,protocal=0)
'''
socket_family有两种:AF_UNIX、AF_INET
socket_type:SOCK_STREAM(TCP协议)、SOCK_DGRAM(UDP协议)
protocal:不用填,默认即可!
'''
1.3.1、基于TCP的socket
服务端
import socket
ip_port = ('127.0.0.1', 8080)
buffer_size = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建套接字
server.bind(ip_port) # bind()即绑定服务端IP地址与端口
server.listen(2) # listen()即最大连接数,半连接池即俗称的并发数!
while True:
connect, client_addr = server.accept() # accept()即阻塞式等待连接
print(f'接收到来自{client_addr} 的消息:')
while True:
# recv()即接收TCP数据,单次最大接收大小,单位为bytes;1024即1KB
receive_data = connect.recv(buffer_size)
print(receive_data.decode('utf-8'))
if len(receive_data) == 0: # 收不到消息后,中断循环,避免无数据传输也死磕在这!
break
connect.send('Hello'.encode('utf-8')) # send()即发送数据
connect.close()
客户端
import socket
ip_port = ('127.0.0.1', 8080)
buffer_size = 1024
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect_ex(ip_port) # 连接远程服务端;connect_ex比connect多了个连接错误时返回异常状态码而不是报错
while True:
msg = input('请输入交互内容,退出请键入quit:').strip()
if len(msg) == 0:
print('内容不能为空!')
continue
elif msg == 'quit':
break
client.send(msg.encode('utf-8'))
data = client.recv(buffer_size)
print(data.decode('utf-8'))
client.close()
测试结果
先启动服务端,接着启动客户端;启动完成后在客户端操作如下:
# 客户端操作
请输入交互内容,退出请键入quit:sanxi
Hello
请输入交互内容,退出请键入quit:quit
Process finished with exit code 0
# 服务端响应
接收到来自('127.0.0.1', 60791) 的消息:
sanxi
# 当客户端close连接后,服务端继续阻塞式等待连接!因为我们服务端的夙愿是永远服务!
1.3.2、基于UDP的socket
UDP因为不需要三次握手四次挥手的过程,因此代码也非常精简,速度也比TCP快很多,除了不靠谱!
服务端
import socket
ip_port = ('127.0.0.1', 8080)
buffer_size = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 创建UDP套接字
server.bind(ip_port)
while True:
receive_data, client_addr = server.recvfrom(buffer_size)
print(f'接收到来自{client_addr} 的消息:')
print(receive_data.decode('utf-8'))
server.sendto('Hello'.encode('utf-8'), client_addr) # sendto()即发送UDP数据,第二个参数为元祖形式的ip+port
客户端
import socket
ip_port = ('127.0.0.1', 8080)
buffer_size = 1024
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
msg = input('请输入交互内容,退出请键入quit:').strip()
if not msg:
continue
elif msg == 'quit':
break
client.sendto(msg.encode('utf-8'), ip_port)
server_data, server_addr = client.recvfrom(buffer_size)
print(server_data.decode('utf-8'), server_addr)
测试结果:
# 客户端
请输入交互内容,退出请键入quit:chrystal
Hello ('127.0.0.1', 8080)
请输入交互内容,退出请键入quit:quit
# 服务端
接收到来自('127.0.0.1', 55139) 的消息:
chrystal
基于上述,可以做聊天软件、时间服务器等小程序!