伪SELECT版

server端

root@iZ947mgy3c5Z:/prodata/scripts# cat fake_select_tcp_server.py
import time
from socket import *


def main():
    # 创建TCP Server套接字
    server_socket = socket(AF_INET, SOCK_STREAM)
    # 设置监听地址端口
    server_port = ('127.0.0.1', 7788)
    # 绑定地址端口
    server_socket.bind(server_port)
    # !!!setblocking这里是关键!!!
    # 默认setblocking为True,也就accept时会阻塞住,但是这里没用多进程或多线程处理
    # 所以如果主进程(主线程)被阻塞,也就意味着无法处理后面TCP连接
    # 所以这里设置为False,也就是不阻塞
    server_socket.setblocking(False)
    # 设置半连接(正在三次握手的连接)和全连接(握手通过的连接)的队列长度
    server_socket.listen(5)
    # 客户端socket列表
    client_socket_list = []
    # 循环开始
    while True:
        # 异常处理为了捕获server套接字创建client套接字失败的情况
        try:
            client_socket, client_addr = server_socket.accept()
        except Exception as e:
            # 这就是创建失败抛出的异常,忽略即可
            # [Errno 11] Resource temporarily unavailable
            pass
        else:
            # 如果client套接字创建成功会将其socket对象append进client_socket_list中
            # 以供后面for循环遍历检查是否socket是否有数据
            client_socket_list.append(client_socket)
            # 打印客户端连接上来信息
            print('{}:{} connected...'.format(*client_addr))

        # 循环遍历检查是否socket是否有数据
        for cs in client_socket_list:
            # 这里有点疑惑,这里印象中好像是会阻塞的,执行起来好像没发现阻塞
            # 难道我之前设置server套接字非阻塞,所以它创建的client套接字也是非阻塞的?
            # 接收客户端socket数据
            client_data = cs.recv(1024)
            # 如果数据长度小于等于0,说明客户端断开了连接
            if len(client_data) <= 0:
                # 从client_socket_list移除,不再检查
                client_socket_list.remove(cs)
                # 打印客户端断开信息
                print('someone disconnect...')
            else:
                # 如果数据长度大于0,则说明客户端传过来数据了,所以打印时间和数据信息
                print('[{}]: {}'.format(time.strftime("%Y-%m-%d %H:%M:%S"), client_data))
                # 数据原封不动发回给客户端,模拟echo功能
                cs.send(client_data)
        # 这里sleep是为了减少CPU消耗,不然直接飙升到90多
        time.sleep(0.1)

if __name__ == '__main__':
    main()

client端

客户端很简单就是开了多线程来发数据

root@iZ947mgy3c5Z:/prodata/scripts# cat multi_thread_client.py 
from socket import *
from multiprocessing import Pool, current_process
from threading import Thread, current_thread
import time

host_port = ('127.0.0.1', 7788)
def worker():
    try:
        client_socket = socket(AF_INET, SOCK_STREAM)
        client_socket.connect(host_port)
        while True:
            time.sleep(1)
            client_socket.send('hi'.encode())

            print('[{}]: {}'.format(time.strftime("%Y-%m-%d %H:%M:%S"), current_thread().name))
    finally:
       client_socket.close()

def main():
    t1 = Thread(target=worker, name="t1")
    t2 = Thread(target=worker, name="t2")
    t3 = Thread(target=worker, name="t3")
    t4 = Thread(target=worker, name="t4")
    t1.start()
    t2.start()
    t3.start()
    t4.start()


if __name__ == '__main__':
    main()

执行效果

server

root@iZ947mgy3c5Z:/prodata/scripts# python3.5 fake_select_tcp_server.py
127.0.0.1:6917 connected...
[2018-01-24 09:39:01]: b'hi'
127.0.0.1:6918 connected...
[2018-01-24 09:39:02]: b'hi'
[2018-01-24 09:39:02]: b'hihi'
127.0.0.1:6919 connected...
[2018-01-24 09:39:03]: b'hi'
[2018-01-24 09:39:03]: b'hi'
[2018-01-24 09:39:03]: b'hihihi'
127.0.0.1:6920 connected...
[2018-01-24 09:39:04]: b'hi'
[2018-01-24 09:39:04]: b'hi'
[2018-01-24 09:39:04]: b'hi'
[2018-01-24 09:39:04]: b'hihihi'
[2018-01-24 09:39:05]: b'hi'
[2018-01-24 09:39:05]: b'hi'
[2018-01-24 09:39:05]: b'hi'
[2018-01-24 09:39:05]: b'hi'
[2018-01-24 09:39:06]: b'hi'
[2018-01-24 09:39:06]: b'hi'
[2018-01-24 09:39:06]: b'hi'
[2018-01-24 09:39:06]: b'hi'

client效果

root@iZ947mgy3c5Z:/prodata/scripts# python3.5 multi_thread_client.py 
[2018-01-24 09:39:01]: t1
[2018-01-24 09:39:01]: t2
[2018-01-24 09:39:01]: t3
[2018-01-24 09:39:01]: t4
[2018-01-24 09:39:02]: t2
[2018-01-24 09:39:02]: t1
[2018-01-24 09:39:02]: t3
[2018-01-24 09:39:02]: t4
[2018-01-24 09:39:03]: t2
[2018-01-24 09:39:03]: t1
[2018-01-24 09:39:03]: t3
[2018-01-24 09:39:03]: t4
[2018-01-24 09:39:04]: t1
[2018-01-24 09:39:04]: t2
[2018-01-24 09:39:04]: t3
[2018-01-24 09:39:04]: t4
[2018-01-24 09:39:05]: t2
[2018-01-24 09:39:05]: t1
[2018-01-24 09:39:05]: t3
[2018-01-24 09:39:05]: t4
[2018-01-24 09:39:06]: t1
[2018-01-24 09:39:06]: t2
[2018-01-24 09:39:06]: t3
[2018-01-24 09:39:06]: t4

总结

关键点其实就几个

  1. 创建服务器套接字接受连接,但是注意千万不要让主线程被服务器套接字阻塞
  2. 获取可以读取的客户端套接字及数据
  3. 处理客户端套接字发送过来的数据

results matching ""

    No results matching ""