多线程实现socket通信服务器端代码

import socket
import threading class MyServer(object):
def __init__(self):
# 初始化socket
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置服务器IP地址
host = '192.168.152.1'
# 设置服务器端口号
port = 4321
# 绑定IP地址和端口
self.server.bind((host, port))
# 设置最大监听数
self.server.listen(5)
# 设置一个字典,用来保存每一个客户端的连接和身份信息
self.socket_mapping = {}
# 设置接收的最大字节数
self.maxSize = 1024 def run(self):
while True:
socket, addr = self.server.accept()
# 发送信息,提示客户端已成功连接
socket.send('success!'.encode('utf-8'))
# 将客户端socket等信息存入字典
self.socket_mapping[socket] = addr
# 创建线程,负责获取键盘输入并发送给客户端
threading.Thread(target=self.send_to_client, args=(socket,)).start()
# 创建线程,负责接收客户端信息并转发给其他客户端
threading.Thread(target=self.recv_from_client, args=(socket,)).start() def send_to_client(self, socket):
"""
获取键盘输入并发送给客户端
:param socket:
:return:
"""
while True:
info = input()
if info == "quit":
socket.close()
for socket in self.socket_mapping.keys():
socket.send(info.encode("utf-8")) def recv_from_client(self, socket):
"""
接收客户端信息并转发给其他客户端
:param socket:
:return:
"""
while True:
recv_info = socket.recv(self.maxSize).decode('utf-8')
print('client{} say: '.format(self.socket_mapping[socket]), recv_info)
for i_socket in self.socket_mapping.keys():
if i_socket != socket:
i_socket.send(recv_info.encode("utf-8")) my_server = MyServer()
my_server.run()

多进程实现socket通信服务器端代码

存在的问题:在与客户端连通后,需要服务器先发送两条消息,之后才能正常通信。

import os
import socket
import sys
from multiprocessing import Process, Manager class MyServer(object):
def __init__(self):
# 初始化socket
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置服务器IP地址
host = '192.168.152.1'
# 设置服务器端口号
port = 4321
# 绑定IP地址和端口
self.server.bind((host, port))
# 设置最大监听数
self.server.listen(5)
# 设置一个字典,用来保存每一个客户端的连接和身份信息
self.socket_mapping = Manager().dict()
# 设置接收的最大字节数
self.maxSize = 1024
# 进程锁
self.share_lock = Manager().Lock() def run(self):
fn = sys.stdin.fileno()
while True:
socket, addr = self.server.accept()
# 发送信息,提示客户端已成功连接
socket.send('success!'.encode('utf-8'))
# 将客户端socket等信息存入字典
self.modify_mapping(self.socket_mapping, addr, socket, self.share_lock)
# 创建进程,负责获取键盘输入并发送给客户端
Process(target=self.send_to_client, args=(addr, fn)).start()
# 创建进程,负责接收客户端信息并转发给其他客户端
Process(target=self.recv_from_client, args=(addr,)).start() def send_to_client(self, addr, fn):
"""
获取键盘输入并发送给客户端
:param addr:
:return:
"""
sys.stdin = os.fdopen(fn)
while True:
info = sys.stdin.readline()
if info == "quit":
self.socket_mapping[addr].close()
for socket in self.socket_mapping.values():
socket.send(info.encode("utf-8")) def recv_from_client(self, addr):
"""
接收客户端信息并转发给其他客户端
:param addr:
:return:
"""
while True:
recv_info = self.socket_mapping.get(addr).recv(self.maxSize).decode('utf-8')
print('client{} say: '.format(addr), recv_info)
for i_addr in self.socket_mapping.keys():
if i_addr != addr:
self.socket_mapping.get(i_addr).send(recv_info.encode("utf-8")) @staticmethod
def modify_mapping(share_var, share_key, share_value, share_lock):
# 获取锁
share_lock.acquire()
# 修改数据
share_var[share_key] = share_value
# 释放锁
share_lock.release() if __name__ == "__main__":
my_server = MyServer()
my_server.run()

异步IO实现socket通信服务器端代码

存在的问题:通信时需要相互发送几次消息后,各自才会收到之前的消息并打印。

import socket
import asyncio
import select class MyServer(object):
def __init__(self):
# 初始化socket
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置服务器IP地址
host = '192.168.152.1'
# 设置服务器端口号
port = 4321
# 绑定IP地址和端口
self.server.bind((host, port))
# 设置最大监听数
self.server.listen(5)
# 设置一个字典,用来保存每一个客户端的连接和身份信息
self.socket_mapping = {self.server: None} # 这里存入self.server是为了充当select.select参数
# 设置接收的最大字节数
self.maxSize = 1024
# 进入事件循环
self.loop = asyncio.get_event_loop() def run(self):
while True:
# select监听请求对象
rret, _, _ = select.select(self.socket_mapping.keys(), [], [])
for r_socket in rret:
if r_socket is self.server:
socket, addr = r_socket.accept()
# 发送信息,提示客户端已成功连接
socket.send('success!'.encode('utf-8'))
# 将客户端socket等信息存入字典
self.socket_mapping[socket] = addr
else:
task = [self.send_to_client(r_socket), self.recv_from_client(r_socket)]
self.loop.run_until_complete(asyncio.gather(*task)) async def send_to_client(self, socket):
"""
获取键盘输入并发送给客户端
:param socket:
:return:
"""
info = input()
if info == "quit":
socket.close()
for socket in self.socket_mapping.keys():
if socket != self.server:
socket.send(info.encode("utf-8")) async def recv_from_client(self, socket):
"""
接收客户端信息并转发给其他客户端
:param socket:
:return:
"""
recv_info = socket.recv(self.maxSize).decode('utf-8')
print('client{} say: '.format(self.socket_mapping[socket]), recv_info)
for i_socket in self.socket_mapping.keys():
if i_socket != socket and i_socket != self.server:
i_socket.send(recv_info.encode("utf-8")) my_server = MyServer()
my_server.run()

客户端代码(使用多线程)

import socket
import threading class MyClient(object):
def __init__(self):
# 初始化socket
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置服务器IP地址
self.host = '192.168.152.1'
# 设置服务器端口号
self.port = 4321
# 设置接收的最大字节数
self.max_size = 1024 def run(self):
# 与服务器建立连接
self.client.connect((self.host, self.port))
# 创建线程,负责获取键盘输入并发送给服务器
threading.Thread(target=self.sned_to_server).start()
# 创建线程,接收服务器信息
threading.Thread(target=self.recv_from_server).start() def sned_to_server(self):
"""
获取键盘输入并发送给服务器
"""
while True:
send_msg = input()
self.client.send(send_msg.encode('utf-8'))
if send_msg == 'quit':
break
self.client.close() def recv_from_server(self):
"""
接收服务器信息
"""
while True:
recv_info = self.client.recv(self.max_size).decode('utf-8')
print('server{} say: '.format((self.host, self.port)), recv_info) my_client = MyClient()
my_client.run()

使用Python实现多线程、多进程、异步IO的socket通信的更多相关文章

  1. Python学习——多线程,异步IO,生成器,协程

    Python的语法是简洁的,也是难理解的. 比如yield关键字: def fun(): for i in range(5): print('test') x = yield i print('goo ...

  2. 多线程/多进程/异步IO

    SOCK_STREAM :TCPSOCK_Dgram :UDP family=AF_INET: 服务器之间的通信AF_INET6: 服务器之间的通信AF_UNIX: Unix不同进程间的通信 永远遵循 ...

  3. Python之路,Day10 - 异步IO\数据库\队列\缓存

    Python之路,Day9 - 异步IO\数据库\队列\缓存   本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitM ...

  4. Day10 - Python协程、异步IO、redis缓存、rabbitMQ队列

    Python之路,Day9 - 异步IO\数据库\队列\缓存   本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitM ...

  5. 从Nginx的Web请求处理机制中剖析多进程、多线程、异步IO

    Nginx服务器web请求处理机制 从设计架构来说,Nginx服务器是与众不同的.不同之处一方面体现在它的模块化设计,另一方面,也是最重要的一方面,体现在它对客户端请求的处理机制上. Web服务器和客 ...

  6. python中同步、多线程、异步IO、多线程对IO密集型的影响

    目录 1.常见并发类型 2.同步版本 3.多线程 4.异步IO 5.多进程 6.总结 1.常见并发类型 I/ O密集型: 蓝色框表示程序执行工作的时间,红色框表示等待I/O操作完成的时间.此图没有按比 ...

  7. Python协程、异步IO

    本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko SS ...

  8. Python高级编程和异步IO并发编程

    第1章 课程简介介绍如何配置系统的开发环境以及如何加入github私人仓库获取最新源码. 1-1 导学 试看 1-2 开发环境配置 1-3 资源获取方式第2章 python中一切皆对象本章节首先对比静 ...

  9. 【Python之路】异步IO

    线程:CPU基本执行单元,可以与同属一个进程的其他线程共享资源,线程是属于进程的. 进程:资源单元,进程一般由程序.数据集.进程控制块三部分组成.一个进程默认有一个主线程, GIL:用于在进程中对所有 ...

  10. python 多协程异步IO爬取网页加速3倍。

    from urllib import request import gevent,time from gevent import monkey#该模块让当前程序所有io操作单独标记,进行异步操作. m ...

随机推荐

  1. 谣言检测——(GCAN)《GCAN: Graph-aware Co-Attention Networks for Explainable Fake News Detection on Social Media》

    论文信息 论文标题:GCAN: Graph-aware Co-Attention Networks for Explainable Fake News Detection on Social Medi ...

  2. Kubernetes 配置管理

    ConfigMap(可变配置管理) 对于应用的可变配置在 Kubernetes 中是通过一个 ConfigMap 资源对象来实现的,我们知道许多应用经常会有从配置文件.命令行参数或者环境变量中读取一些 ...

  3. 第五章:Admin管理后台 - 3:Admin文档生成器

    Django的admindocs应用可以从模型.视图.模板标签等地方获得文档内容. 一.概览 要激活admindocs,请按下面的步骤操作: 在INSTALLED_APPS内添加django.cont ...

  4. 第六章:Django 综合篇 - 8:信号 signal

    django自带一套信号机制来帮助我们在框架的不同位置之间传递信息.也就是说,当某一事件发生时,信号系统可以允许一个或多个发送者(senders)将通知或信号(signals)发送给一组接受者(rec ...

  5. WPF绘制圆形调色盘

    本文使用writeableBitmap类和HSB.RGB模式来绘制圆形的调色盘. 开源项目地址:https://github.com/ZhiminWei/Palette RGB为可见光波段三个颜色通道 ...

  6. C++面向对象编程之C++11语法糖

    1.variadic template(模板参数可变化) template... type就是说有可变模板参数,作为参数使用时类型就是 类型后 + ... ,例如type... / type& ...

  7. 修改端口号还是无法启动第二个tomcat的原因

    问题:我的服务器是Tomcat7.0.20,修改完所有端口之后(shutdown端口.http端口.https端口.ajp端口),启动一个就不能启动另一个. 两 个startup.bat最前面加上一句 ...

  8. Annocation(注解)的使用示例

    示例一:生成文档相关的注解示例二:在编译时进行格式检查(JDK内置的三个基本注解)@Override: 限定重写父类方法, 该注解只能用于方法@Deprecated: 用于表示所修饰的元素(类, 方法 ...

  9. Ubuntu安装错误 server64 busybox-initramfs安装失败

    因为想试试在Linux系统上爆破 所以安装了一下Ubuntu.第一次安装包报了个server64 busybox-initramfs.在安装系统那边.我一直还以为是我磁盘分配错了. 后来在网上找了资料 ...

  10. springboot+mybatis+shiro项目中使用shiro实现登录用户的权限验证。权限表、角色表、用户表。从不同的表中收集用户的权限、

    要实现的目的:根据登录用户.查询出当前用户具有的所有权限.然后登录系统后.根据查询到的权限信息进行不同的操作. 以下的代码是在搭好的框架之下进行的编码. 文章目录 核心实现部分. 第一种是将用户表和角 ...