Python socket实现多对多全双工通信的方法
作者:小銍 发布时间:2023-05-02 17:31:38
标签:Python,socket,全双工,通信
服务器:#server.py
#!/usr/bin/env python
#-*-coding:utf-8-*-
import sys
import struct#将字符串打包为二进制流进行网络传输
import select#
import signal#用于捕获中断信号
import cPickle#将python对象进行序列化:dumps将python对象序列化保存为字符串,loads与之相反
from socket import *
HOST = ''
def send(channel,*args):#发送数据
buffer = cPickle.dumps(args)
value = htonl(len(buffer))
size = struct.pack("L",value)
channel.send(size)
channel.send(buffer)
def receive(channel):#接收数据
size = struct.calcsize("L")
size = channel.recv(size)
try:
size = ntohl(struct.unpack("L",size)[0])#socket.ntohl(参考:http://blog.csdn.net/tatun/article/details/7194973)
except struct.error,e:
return ''
buf = ''
while len(buf) < size:
buf += channel.recv(size-len(buf))
return cPickle.loads(buf)[0]#恢复python对象
class ChatServer(object):
def __init__(self,PORT,backlog = 5):
self.clients = 0
self.clientmap = {}
self.outputs = [] #Client会话列表
self.server = socket(AF_INET, SOCK_STREAM)
self.server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)#重用套接字地址
self.server.bind((HOST,PORT))
self.server.listen(backlog)
signal.signal(signal.SIGINT,self.signalhandler)#使用signal模块捕获中断操作 SIGINT中断进程(ctrl+c), SIGTERM 终止进程,SIGKILL杀死进程,SIGALRM 闹钟信号
def signalhandler(self,signum,frame):#中断处理方法
print "Shutting down server ..."
for output in self.outputs:
output.close()
self.server.close()
def get_client_name(self,client):
info = self.clientmap[client]
host,port,name = info[0][0],info[0][1],info[1]
return ':'.join((('@'.join((name,host))),str(port)))
def run(self):
inputs = [self.server]
print 'Waiting for connect...'
while True:
try:
readable,writeable,execption = select.select(inputs,self.outputs,[])
except select.error,e:
break
for sock in readable:
if sock == self.server:#服务器端接收
client,address = self.server.accept()
print "Chat server: connected from",address
self.clients += 1
cname = receive(client)
send(client,str(address[0]))
inputs.append(client)
self.clientmap[client] = (address,cname)
msg = "(Connected : New Client(%d) from %s)\n"%(self.clients,self.get_client_name(client))
message = "At present, only one of you is in the chat room!"
if self.clients == 1:
send(client,message)
for output in self.outputs:
send(output,msg)
self.outputs.append(client)#将开始回话的client加入Client回话列表
#elif sock == sys.stdin:
#break
else:
try:
data = receive(sock)
if data:
msg = '[' + self.get_client_name(sock)+ '] >> ' + data
for output in self.outputs:
if output!=sock:
send(output,msg)
else:
self.clients-=1
sock.close()
inputs.remove(sock)
self.outputs.remove(sock)
msg = '(Now hung up: Client from %s)'%self.get_client_name(sock)
message = "At present, only one of you is in the chat room!"
for output in self.outputs:
send(output,msg)
if self.clients == 1:
send(self.outputs[0],message)
except error,e:
inputs.remove(sock)
self.outputs.remove(sock)
self.server.close()
if __name__ == "__main__":
server = ChatServer(6004)
server.run()
客户端:#client.py
#!/usr/bin/env python
#-*-coding:utf-8-*-
from server import send,receive
from socket import *
import sys
import select
import cPickle
import struct
import signal
class ChatClient(object):
def __init__(self,name):
self.name = name
self.connected = False
self.host = 'localhost'
self.port = 6004
try:
self.sock = socket(AF_INET,SOCK_STREAM)
self.sock.connect((self.host,self.port))
self.connected = True
send(self.sock,self.name)
data= receive(self.sock)
addr = data
except error,e:#socket.serro
print 'Failed to connect to chat server'
sys.exit(1)
def run(self):
while True:
try:
readable,writeable,exception = select.select([0,self.sock],[],[])
for sock in readable:
if sock == 0:
data = sys.stdin.readline().strip()
if data:
send(self.sock,data)
else:
data=receive(self.sock)
if not data:
print 'Client shutting down.'
self.connected = False
break
else:
sys.stdout.write(data+'\n')
sys.stdout.flush()
except KeyboardInterrupt:
print 'Client interrupted'
self.sock.close()
break
if __name__ == "__main__":
name = raw_input("Please input login name > ")
client=ChatClient(name)
client.run()
来源:https://blog.csdn.net/zhidetian/article/details/53470849
0
投稿
猜你喜欢
- 导言Python官方文档对于内置函数的介绍较为简略,但这些内置函数在日常工作中却扮演着不可或缺的角色。为了更加便捷地使用和查阅这些函数,笔者
- 例如<div id="info"><span><span class='pl
- 首先安装pip install ruamel.yaml用于修改yaml文件#coding:utf-8from ruamel import y
- 简介特点请求你所要的数据,不多不少获取多个资源,只用一个请求描述所有的可能,类型系统几乎所有语言支持文档Graphene-PythonGra
- 前言本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理基本开发环境 Python
- 一、添加user到group第一种:user.groups.add(1) # add by id第二种:from django.contri
- 本文实例讲述了Python 网络编程之TCP客户端/服务端功能。分享给大家供大家参考,具体如下:demo.py(TCP客户端):import
- 前几天有个人退群了。起因很简单,他问了一个问题,没人回答,于是说要退群,后来我看到了,给了个链接,说这个问题已经说过好多遍了,于是他就退了。
- 1、类变量、实例变量概念类变量:类变量就是定义在类中,但是在函数体之外的变量。通常不使用self.变量名赋值的变量。类变量通常不作为类的实例
- 本文实例讲述了Python中逗号的三种作用。分享给大家供大家参考。具体分析如下:最近研究python 遇到个逗号的问题 一直没弄
- 就javascript来说,iframe创建的框架和frameset创建的框架一样。这里有个关系图,做个笔记。图片源自《javascript
- ff默认不让改 statusopera9 测试通过ie6 测试通过这东西是给统计部门用的,分析用户习惯以改良网站布局
- 经常在网站上看到诸如www.abc.com/?news或者www.abc.com/?id=123这样的网址,一开始觉得很神秘,其实现在看多了
- 如下所示:import torchfrom torch.autograd import Variableimport matplotlib.
- 本文实例讲述了Python简单读写Xls格式文档的方法。分享给大家供大家参考,具体如下:1. 模块安装使用pip install命令安装,即
- 概述从今天开始, 小白我将带领大家一起来补充一下 数据库的知识.数据控制语言数据控制语言 (Data Control Language) 是
- 在前面的DRF系列教程中,我们以博客为例介绍了序列化器, 使用基于类的视图APIView和ModelViewSet开发了针对文章资源进行增删
- 在JavaScript前端开发工作中,由于浏览器兼容性等问题,我们会经常用到“停止事件冒泡”和“阻止浏览器默认行为”。1..停止事件冒泡//
- Numpy是Numerical Python extensions的缩写,字面意思是Python数值计算扩展。Numpy是python中众多
- 1:mysql是我们使用最多的数据库,如果在日常中正确的对mysql数据进行备份,下面我们就来做这事,通过脚本来实现############