Python socket实现多对多全双工通信的方法


Posted in Python onFebruary 13, 2019

服务器:#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()

以上这篇Python socket实现多对多全双工通信的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python3搜索及替换文件中文本的方法
May 22 Python
Python中str.format()详解
Mar 12 Python
python遍历序列enumerate函数浅析
Oct 17 Python
python微信好友数据分析详解
Nov 19 Python
在Qt中正确的设置窗体的背景图片的几种方法总结
Jun 19 Python
深入解析神经网络从原理到实现
Jul 26 Python
python将字典列表导出为Excel文件的方法
Sep 02 Python
tensorflow实现训练变量checkpoint的保存与读取
Feb 10 Python
django rest framework 自定义返回方式
Jul 12 Python
详解PyQt5中textBrowser显示print语句输出的简单方法
Aug 07 Python
python 8种必备的gui库
Aug 27 Python
python opencv通过按键采集图片源码
May 20 Python
对python文件读写的缓冲行为详解
Feb 13 #Python
python单线程文件传输的实例(C/S)
Feb 13 #Python
Python 实现文件打包、上传与校验的方法
Feb 13 #Python
使用python3构建文件传输的方法
Feb 13 #Python
对python 自定义协议的方法详解
Feb 13 #Python
Python 实现两个服务器之间文件的上传方法
Feb 13 #Python
Python魔法方法详解
Feb 13 #Python
You might like
php array的学习笔记
2012/05/10 PHP
js继承的实现代码
2010/08/05 Javascript
flexigrid 参数说明
2010/11/23 Javascript
jquery实现图片等比例缩放以及max-width在ie中不兼容解决
2013/03/21 Javascript
关闭ie窗口清除Session的解决方法
2014/01/10 Javascript
jQuery的:parent选择器定义和用法
2014/07/01 Javascript
node.js中的fs.lchownSync方法使用说明
2014/12/16 Javascript
jQueryMobile之Helloworld与页面切换的方法
2015/02/04 Javascript
jquery 插件实现多行文本框[textarea]自动高度
2015/03/04 Javascript
jQuery聚合函数实例
2015/05/21 Javascript
浅析js中substring和substr的方法
2015/11/09 Javascript
canvas 弹幕效果(实例分享)
2017/01/11 Javascript
JavaScript之浏览器对象_动力节点Java学院整理
2017/07/03 Javascript
微信小程序中使用ECharts 异步加载数据的方法
2018/06/27 Javascript
使用iView Upload 组件实现手动上传图片的示例代码
2018/10/01 Javascript
vue中promise的使用及异步请求数据的方法
2018/11/08 Javascript
微信小程序实现省市区三级地址选择
2020/06/21 Javascript
Node.js 多进程处理CPU密集任务的实现
2019/05/26 Javascript
Vue组件间的通信pubsub-js实现步骤解析
2020/03/11 Javascript
JavaScript实现简易计算器小功能
2020/10/22 Javascript
Python 异常处理实例详解
2014/03/12 Python
Python读取txt内容写入xls格式excel中的方法
2018/10/11 Python
Python之NumPy(axis=0 与axis=1)区分详解
2019/05/27 Python
django 解决扩展自带User表遇到的问题
2020/05/14 Python
浅谈cv2.imread()和keras.preprocessing中的image.load_img()区别
2020/06/12 Python
使用HTML5 Canvas API控制字体的显示与渲染的方法
2016/03/24 HTML / CSS
StubHub哥伦比亚:购买和出售您的门票
2016/10/20 全球购物
乐高奥地利官方商店:LEGO Shop AT
2019/07/16 全球购物
法警的竞聘演讲稿
2014/01/02 职场文书
大学运动会通讯稿
2014/01/28 职场文书
幼儿教师培训感言
2014/03/08 职场文书
生产文员岗位职责
2014/04/05 职场文书
关爱残疾人演讲稿
2014/05/24 职场文书
立案决定书范文
2015/06/24 职场文书
运动会致辞稿
2015/07/29 职场文书
小学二年级语文教学反思
2016/03/03 职场文书