Socket: 应用层与TCP/IP协议通信的中间软件抽象层,把复杂的TCP/IP协议隐藏在socket接口后面
也可理解为ip + port , ip用来标识互联网中的一台主机的位置,port用来标识这太计算器上的一个应用程序,ip 地址是配置到网卡上的,port是应用程序开启的,ip与port的绑定就标识了互联网中独一无二的应用程序
套接字家族: AF_UNIX: 两个套接字进程运行在同一机器,可以通过访问同一个文件系统简介完成通信
AF_INET: 被用于ipv6,网络编程中,我们只使用AF_INET
套接字工作流程:
服务器: 先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用 accept阻塞,等待客户端连接
客户端: 初始化Socket, 然后连接服务器conncet, 如果连接成功,客户端,服务器连接建立,客户端发送数据请求,服务端接收请求并处理请求,然后把回应数据发送给客户端
#基于TCP 的服务端 import socket server = socket.socket() # 相当于:server = socket.socket(AF_INET,socket.SOCK_STREAM,0) # 参数(socket家族,socket类型(SOCK_STREAM 对应TCP, SOCK_DGRAM 对应UDP) server.bind(('ip',端口)) server.listen() client,address = server.accept() data = client.recv(1024) print(data.decode('utf-8')) client.send('msg'.encode('utf-8')) client.close() server.close()
# 服务端循环收发模板
import socket
server = socket.socket()
server.bind(('ip',端口))
server.listen()
while True:
# 连接循环,可以不断接收连接
client,address = server.accept()
while True:
try:
#如果是windows,客户端强行关闭,会抛出异常
#如果是Linux,不会抛出异常会死循环收到空的数据包
data = client.recv(1024)
if not data:
client.close()
break
print(data.decode('utf-8'))
client.send(data.encode('utf-8'))
except ConnectionResetError:
print('客户端强行关闭连接')
client.close()
break
server.close()
# 基于TCP 的客户端 import socket client = socket.socket() client.connect(('ip',端口)) client.send('msg'.encode('utf-8')) #对应服务端中的resv data = client.resv(1024) #对应服务端中的send print(data.decode('utf-8')) client.close()
#客户端循环收发模板
import socket
client = socket.socket()
client.connect(('ip',端口))
while True:
msg = input('>>>: ')
client.send(msg.encode('utf-8')) #对应服务端中的resv
data = client.resv(1024) #对应服务端中的send
print(data.decode('utf-8'))
client.close()
import socket #三个参数(套接字家族,socket 类型) server = socket.socket(AF_INET,socket.SOCK_DGRAM,0) server.bind(("ip",端口)) # UDP 不需要listen 和 accept while True: # 循环收发 data,address = server.recvfrom(1024) # 阻塞,直到收到数据为止 # 返回的值为 数据和对方的ip地址和端口号(所以地址为一个元组,ip和端口号) server.sendto(msg.encode('utf-8'),address) # 发送信息时两个参数,一个数据和一个地址 server.close()
#基于UDP的客户端socket import socket client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0) # 不需要连接服务端,直接发送信息 while True: # 循环收发 msg = input('>>>>: ') client.sendto(msg,('ip',端口)) data,address = client.recvfrom(1024) client.close()
UDP 是无链接的,先启动哪一端都不会报错
缓冲区: 操作系统分配的一部分内存,专门用于存放一些来不及处理的数据
发送方: 数据先给操作系统,操作系统不可能同一时间处理,所以操作系统需要一个缓冲区,等
操作系统有空后会自动到缓冲区那数据进行处理
半连接: 三次握手只连接了一半,当服务器响应了客户端第一次请求会等待客户端发送的ack信息
发生原因: 1 客户端出现问题吗,无法返回ack (有可能是syn洪水攻击,不断产生半连接,使服务 器无法处理正常请求)
2 服务器来不及处理客户端请求
半连接池: 是一个容器,系统自动将半连接放入容器中
服务端的 server.listen(5) 的参数表明设置的最大的半连接数(为确保服务器资源不被耗尽)