Python系列 之 socket模块 - 非阻塞模式

socket模块学习

非阻塞模式

socket的默认情况下是阻塞模式:socket.accept()方法在没有接受到连接之前不能处理已经建立连接的其他操作,以及在recv()方法或者其他接受数据的方法时候都是阻塞的,如果没有接受到数据就会一直处于阻塞状态,来等待接受数据,这种情况只有通过开启新的进程或者线程来解决来自不同客户端的连接请求或者接受数据;socket可以支持非阻塞的模式;可以使用以下两种方法来设置socket的非阻塞模式:

# 设置套接字为阻塞或非阻塞模式:如果 flag 为 false,则将套接字设置为非阻塞,否则设置为阻塞。
# socket.setblocking(flag)
# 如果value赋为 0,则套接字将处于非阻塞模式。如果指定为 None,则套接字将处于阻塞模式。
# socket.settimeout(value)
# 阻塞
sock.setblocking(True)
sock.settimeout(None)
# 非阻塞
sock.setblocking(False)
sock.settimeout(0.0)

在非阻塞模式下可以实现在单线程模式下实现与多个客户端连接的交互:

非阻塞模式的服务端:

# demo_socket_server_2.py文件
import logging
import socket

logging.basicConfig(level=logging.DEBUG,
                    format="%(asctime)s>%(message)s", datefmt="%Y-%m-%d %H:%M:%S")
logger = logging.getLogger(__name__)


class ServerClass(object):
    """docstring for ServerClass"""

    def __init__(self):
        self.__HOST = "127.0.0.1"
        self.__PORT = 9999
        self.ADDR = (self.__HOST, self.__PORT)
        self.__TCP_SOCKET = socket.socket(
            family=socket.AF_INET, type=socket.SOCK_STREAM)
        # 设置非阻塞
        # self.__TCP_SOCKET.setblocking(False)
        self.__TCP_SOCKET.settimeout(0.0)
        # 用来存放套接字对象的列表
        self.connlist = list()

    def start_server(self):
        with self.__TCP_SOCKET as sock:
            sock.bind(self.ADDR)
            sock.listen()
            logger.info("Server is Running")
            while True:
                try:
                    conn, addr = sock.accept()
                    # logger.info(conn)
                    # 将连接的套接字对象设置为非阻塞
                    conn.setblocking(False)
                    msg = f"Hi,{
     addr}"
                    self.send_data(conn, msg)
                    # 添加到列表
                    self.connlist.append(conn)
                # 如果没有连接进来需要捕获BlockingIOError异常
                except BlockingIOError as e:
                    pass
                    # logger.debug("没有新的客户端连接")
                # 循环套接字对象列表 进行收发数据
                for conn in self.connlist:
                    msg = self.recv_data(conn)
                    self.send_data(conn, msg)

    def recv_data(self, conn):
        """接收数据"""
        try:
            msg = conn.recv(1024).decode("utf-8")
            if not msg or msg in ["quit"]:
                logger.debug("断开连接")
                # 将套接字对象从列表移除
                self.connlist.remove(conn)
            else:
                logger.info(msg)
                return msg
        except IOError as e:
            pass
            # logger.debug("没有接收到数据")

    def send_data(self, conn, msg):
        """发送数据"""
        if msg:
            msg = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值