Python协程之socket单线程下使用协程实现高并发

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haeasringnar/article/details/79978751

先来看看服务端代码:

import sys,socket,time,gevent
from gevent import socket,monkey
monkey.patch_all()
import threading

def server(port):
    s = socket.socket()
    s.bind(('0.0.0.0',port))
    s.listen(500)
    while True:
        cli,addr = s.accept()
        # 建立一个协程去处理这个链接  这里是起一个协程,然后向链接对象传给写好的处理对象
        # 这里的意思就是,每来一个链接就启动一个协程去处理
        # 这样就是启动了一个并发处理连接的方法
        gevent.spawn(handle_requset,cli)
        # 开启线程的方式启动并发效果
        # t = threading.Thread(target=handle_requset,args=(cli,))
        # t.start()

def handle_requset(conn):
    try:
        while True:
            data = conn.recv(1024)
            if not data:
                conn.shutdown(socket.SHUT_WR) #这里就是关闭客户端 使用break方法也是一样的
                # print('并没有收到内容')
            else:
                print('recv:', data.decode())
            conn.send('ok'.encode('utf-8'))
    except Exception as e:
        print(e)
    finally:
        conn.close()

if __name__ == '__main__':
    server(9999)

然后开客户端代码:

import socket

HOST = 'localhost'
PORT = 9999
def conn_one():
    s = socket.socket()
    s.connect((HOST,PORT))
    while True:
        msg = input('>>:').strip()
        s.send(msg.encode('utf-8'))
        # s.send(('hello ').encode('utf-8'))
        data = s.recv(1024)
        print('recved:',data.decode())
    s.close()

conn_one()

# 这是开启100个连接并发
import socket
import threading

# def sock_conn(num):
#     client = socket.socket()
#     client.connect((HOST,PORT))
#     while True:
#         client.send(('hello %d'%num).encode('utf-8'))
#         data = client.recv(1024)
#         print("[%s]recv from server:" % threading.get_ident(), data.decode())
#     client.close()
#
# for i in range(1,101):
#     t = threading.Thread(target=sock_conn,args=(i,))
#     t.start()

'''
综述:
通常,我们写服务器处理模型的程序时,有以下几种模型:
(1)每收到一个请求,创建一个新的进程,来处理该请求;
(2)每收到一个请求,创建一个新的线程,来处理该请求;
(3)每收到一个请求,放入一个事件列表,让主进程通过非阻塞I/O方式来处理请求
上面的几种方式,各有千秋,
第(1)中方法,由于创建新的进程的开销比较大,所以,会导致服务器性能比较差,但实现比较简单。
第(2)种方式,由于要涉及到线程的同步,有可能会面临死锁等问题。
第(3)种方式,在写应用程序代码时,逻辑比前面两种都复杂。
综合考虑各方面因素,一般普遍认为第(3)种方式是大多数网络服务器采用的方式
方式二:就是事件驱动模型
目前大部分的UI编程都是事件驱动模型,如很多UI平台都会提供onClick()事件,这个事件就代表鼠标按下事件。事件驱动模型大体思路如下:
1. 有一个事件(消息)队列;
2. 鼠标按下时,往这个队列中增加一个点击事件(消息);
3. 有个循环,不断从队列取出事件,根据不同的事件,调用不同的函数,如onClick()、onKeyDown()等;
4. 事件(消息)一般都各自保存各自的处理函数指针,这样,每个消息都有独立的处理函数;
'''

在自己的pycharm中开启多个连接试一试吧

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页