网络编程并发问题
单进程设置为非阻塞
from socket import *
# 创建一个对象
tcp_server = socket(AF_INET, SOCK_STREAM)
# 设置对象为非阻塞
tcp_server.setblocking(False)
# 绑定地址和端口
tcp_server.bind(("", 6667))
# 设置监听的数量
tcp_server.listen(3)
socket_lists = []
while True:
# 等待连接
try:
new_socket, address = tcp_server.accept()
# 设置新socket为非阻塞
new_socket.setblocking(False)
socket_lists.append((new_socket, address))
except:
pass
else:
print(address)
for sock, address in socket_lists:
try:
data = sock.recv(1024)
except:
pass
else:
if data:
print(f"接收到{address}信息: {data.decode('gb2312')}")
else:
# 关闭连接
sock.close()
socket_lists.remove((sock, address))
多进程并发服务器
from socket import *
from multiprocessing import Process
def rec_data(new_socket, address):
while True:
data = new_socket.recv(1024)
if data:
print(f"接收到{address}信息: {data.decode('gb2312')}")
else:
# 关闭连接
new_socket.close()
def main():
# 创建一个对象
tcp_server = socket(AF_INET, SOCK_STREAM)
# 绑定地址和端口
tcp_server.bind(("", 6667))
# 设置监听的数量,超过3个就不再接收,此时的tcp_server只能够接听
tcp_server.listen(3)
while True:
# 接收数据,获取新的socket,new_socket即可以接收也可以发送
new_socket, address = tcp_server.accept()
print(address)
p = Process(target=rec_data, args=(new_socket, address))
p.start()
new_socket.close()
if __name__ == '__main__':
main()
多线程并发服务器
from socket import *
from threading import Thread
def rec_data(new_socket, address):
while True:
data = new_socket.recv(1024)
if data:
print(f"接收到{address}信息: {data.decode('gb2312')}")
else:
# 关闭连接
new_socket.close()
def main():
# 创建一个对象
tcp_server = socket(AF_INET, SOCK_STREAM)
# 绑定地址和端口
tcp_server.bind(("", 6667))
# 设置监听的数量,超过3个就不再接收,此时的tcp_server只能够接听
tcp_server.listen(3)
while True:
# 接收数据,获取新的socket,new_socket即可以接收也可以发送
new_socket, address = tcp_server.accept()
p = Thread(target=rec_data, args=(new_socket, address))
p.start()
print(address)
# new_socket.close()
if __name__ == '__main__':
main()
IO多路复用(轮询方式)
import select
from socket import *
def main():
# 创建一个对象
tcp_server = socket(AF_INET, SOCK_STREAM)
tcp_server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
# 绑定地址和端口
tcp_server.bind(("", 6667))
# 设置监听的数量,超过3个就不再接收,此时的tcp_server只能够接听
tcp_server.listen(3)
sock_lists = [tcp_server]
while True:
socket_lists, _, _ = select.select(sock_lists, [], [])
for sock in socket_lists:
if sock == tcp_server:
new_socket, address = tcp_server.accept()
print(address)
sock_lists.append(new_socket)
else:
data = sock.recv(1024)
if data:
print(f"接收到{data.decode('gb2312')}")
else:
sock.close()
sock_lists.remove(sock)
if __name__ == '__main__':
main()
epoll多路复用(事件通知机制)
from socket import *
import select
def main():
# 创建对象
tcp_server = socket(AF_INET, SOCK_STREAM)
tcp_server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
# 绑定ip和端口
tcp_server.bind(("", 2223))
# 设置监听
tcp_server.listen(5)
epoll = select.epoll()
epoll.register(tcp_server.fileno(), select.EPOLLIN)
clients = {}
while True:
epoll_list = epoll.poll()
for fd, events in epoll_list:
print(fd, events)
if fd == tcp_server.fileno():
new_socket, address = tcp_server.accept()
print(address)
epoll.register(new_socket.fileno(), select.EPOLLIN)
# 将新生成的socket对象存储到字典中
clients[new_socket.fileno()] = new_socket
else:
data = clients[fd].recv(1024)
if data:
print(f"接收到{data.decode('gb2312')}")
else:
clients[fd].close()
# 注销文件符
epoll.unregister(fd)
# 删除socket对象
del clients[fd]
if __name__ == '__main__':
main()
select和epoll的区别
select: 有连接限制 32位系统 : 1024个, 64位系统:2048个. 采用轮询机制
epoll: 没有连接限制,采用事件通知机制