Python socket模拟客户端一直接收服务端数据,同时不影响客户端发送数据

客户端程序:client.py

# -*- coding: utf-8 -*-
import socket
improt select
import threading
from time import sleep

def start_client():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect(('127.0.0.1', 8000))
    # 创建线程锁,防止主线程socket被close了,子线程还在recv而引发的异常
    socket_lock = threading.Lock()

    def read_thread_method():
        while True: 
            if not sock:  # 如果socket关闭,退出
                break
            # 使用select监听客户端(这里客户端需要不停接收服务端的数据,所以监听客户端)
            # 第一个参数是要监听读事件列表,因为是客户端,我们只监听创建的一个socket就ok
            # 第二个参数是要监听写事件列表,
            # 第三个参数是要监听异常事件列表,
            # 最后一个参数是监听超时时间,默认永不超时。如果设置了超时时间,过了超时时间线程就不会阻塞在select方法上,会继续向下执行
            # 返回参数 分别对应监听到的读事件列表,写事件列表,异常事件列表
            rs, _, _ = select.select([sock], [], [], 10)
            for r in rs:  # 我们这里只监听读事件,所以只管读的返回句柄数组
                socket_lock.acquire()  # 在读取之前先加锁,锁定socket对象(sock是主线程和子线程的共享资源,锁定了sock就能保证子线程在使用sock时,主线程无法对sock进行操作)

                if not sock:  # 这里需要判断下,因为有可能在select后到加锁之间socket被关闭了
                    socket_lock.release()
                    break

                data = r.recv(1024)  # 读数据,按自己的方式读

                socket_lock.release()  # 读取完成之后解锁,释放资源

                if not data:
                    print 'server close'
                else:
                    print data

    # 创建一个线程去读取数据
    read_thread = threading.Thread(target=read_thread_method)
    read_thread.setDaemon(True)
    read_thread.start()

    # 测试不断写数据
    for x in range(10):
        print x
        sock.send('hello')
        sleep(.1)  # 交出CPU时间,否则其他线程只能看着

    # 清理socket,同样道理,这里需要锁定和解锁
    socket_lock.acquire()
    sock.close()
    sock = None
    socket_lock.release()

if __name__ == "__main__":
    start_client()

写一个服务端程序,测试客户端程序
server.py

# -*- coding: utf-8 -*-
import socket
import select

def start_server():
    server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_sock.bind("127.0.0.1", 8000)
    server_sock.listen(2)
    read_inputs = [s_handler, ]

    while True:
        print "waiting for connection..."
        rs, _, _ = select.select(read_inputs, [], [], 10)
        print 'receive new: %r %r' % (rs, read_inputs)
        for r_handler in rs:
            if r_handler is s_handler:
                c_socket, c_address = r_handler.accept()
                read_inputs.append(c_socket)
            else:
                data = r_handler.recv(1024)
                if not data:
                    read_inputs.remove(r_handler)
                else:
                    r_handler.send('demo')
                    print data

if __name__ == "__main__":
    start_server()

猜你喜欢

转载自blog.csdn.net/jia227/article/details/72962786