先来看看服务端代码:
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中开启多个连接试一试吧