1、套接字介绍
socket起源于Unix,遵循“一切皆文件”出发点,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。
在设计模式中,Socket把复杂的TCP/IP协议族隐藏在Socket接口后面,Socket去组织数据,以符合指定的协议。Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。
2、套接字服务过程(TCP协议)
3、一个简单服务器示例
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
· 协议族,通常为AF_INET,表示互联网协议族(TCP/IP协议族)。
· socket类型:SOCK_STREAM,流式套接字提供可靠的、面向连接的通信流:它使用TCP协议,从而保证了数据传输的正确性和顺序性(TCP:可靠的、重传、有连接的,一般用于控制命令)。
3.1 server
s.listen() 0成功,-1失败
· 服务器端套接字一直处于监听状态,不受客户端连接的影响。
· 接收到客户端套接字的连接请求,就会响应客户端套接字的请求,建立一个新的线程,并把服务器端套接字的描述发送给客户端。
s.accept()
· 返回新的socket,用于完成和本次接受的客户端通信。从已完成连接的列表,返回连接;没有连接,线程则进入阻塞睡眠状态。
import socket
import struct
import json
from tqdm import tqdmserver=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
serversocketaddr=('127.0.0.1',12345)
server.bind(serversocketaddr)
server.listen(1024)clientsocket,addr=server.accept()
print("Connection from %s has been established!" % clientsocket)# recv多条数据出现粘包现象,可通过增加header解决,规定内容长度,获取指定内容
print("--------------BEGIN-----------------")
header_len_bytes=clientsocket.recv(4) # 接收报头长度,固定4字节
header_len=struct.unpack("i",header_len_bytes)[0]
header=clientsocket.recv(header_len).decode()
header=json.loads(header)
file_size=header["file_size"]
file_data=clientsocket.recv(file_size)print("[{}]{}".format(type(file_data),file_data))
print("--------------END-----------------","\n")
server.close()
3.2 client
import socket
import os.path
import json
import structclient=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
serversocketaddr=('127.0.0.1',12345)
client.connect(serversocketaddr)file_name="/Users/test/client.png"
file_size=os.path.getsize(file_name)
with open(file_name,'rb') as file:file_data=file.read()header = {"file_size": file_size,"file_name": file_name}header_bytes = json.dumps(header).encode()header_length = struct.pack("i", len(header_bytes))client.send(header_length)client.send(header_bytes)# client.sendall(file_data)client.send(b"<END>")client.close()
3.3 data exchange
· 内容以字节码传输(bytes)
· s.send() 发送内容,只支持字节类型.多个数据包存在粘包情况,需要处理。
· s.sendall() 发送数据,直到所有的数据都发送完成或报错
3.4 RUN(控制台)
· 开始进程
/usr/local/bin/python3.7 server_file_name #python运行目录 +运行文件
/usr/local/bin/python3.7 client_file_name
· 结束进程
sudo lsof -i :port # 终端查询当前端口的详情,获取到PID
kill -9 PID