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 相关文章推荐
编写Python脚本把sqlAlchemy对象转换成dict的教程
May 29 Python
在Django的视图中使用form对象的方法
Jul 18 Python
详解Python3 中hasattr()、getattr()、setattr()、delattr()函数及示例代码数
Apr 18 Python
Django 跨域请求处理的示例代码
May 02 Python
Python2.7环境Flask框架安装简明教程【已测试】
Jul 13 Python
Python开启线程,在函数中开线程的实例
Feb 22 Python
python中几种自动微分库解析
Aug 29 Python
Python3常见函数range()用法详解
Dec 30 Python
Python使用qrcode二维码库生成二维码方法详解
Feb 17 Python
python实现跨excel sheet复制代码实例
Mar 03 Python
TensorFlow固化模型的实现操作
May 26 Python
Python wordcloud库安装方法总结
Dec 31 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 fopen函数用法实例讲解
2019/02/15 PHP
jquery 常用操作方法
2010/01/28 Javascript
JavaScript遍历table表格中的某行某列并打印其值
2014/07/08 Javascript
流量统计器如何鉴别C#:WebBrowser中伪造referer
2015/01/07 Javascript
jQuery实现可用于博客的动态滑动菜单
2015/03/09 Javascript
JavaScript数组方法总结分析
2016/05/06 Javascript
详解angularjs popup-table 弹出框表格指令
2017/09/20 Javascript
详解Vue中使用插槽(slot)、聚类插槽
2019/04/12 Javascript
layui弹出框Tab选项卡的示例代码
2019/09/04 Javascript
layUI使用layer.open,在content打开数据表格,获取值并返回的方法
2019/09/26 Javascript
webpack 动态批量加载文件的实现方法
2020/03/19 Javascript
React生命周期原理与用法踩坑笔记
2020/04/28 Javascript
javascript中layim之查找好友查找群组
2021/02/06 Javascript
举例讲解Python中的算数运算符的用法
2015/05/13 Python
PyQt 线程类 QThread使用详解
2017/07/16 Python
Python数据结构之单链表详解
2017/09/12 Python
简单了解OpenCV是个什么东西
2017/11/10 Python
使用pygame模块编写贪吃蛇的实例讲解
2018/02/05 Python
python中实现数组和列表读取一列的方法
2018/04/03 Python
Python 对输入的数字进行排序的方法
2018/06/23 Python
解决json中ensure_ascii=False的问题
2020/04/03 Python
call在Python中改进数列的实例讲解
2020/12/09 Python
CSS3属性选择符介绍
2008/10/17 HTML / CSS
介绍一下.net和Java的特点和区别
2012/09/26 面试题
教师自我评价范文
2013/12/16 职场文书
服装行业创业计划书范文
2014/02/05 职场文书
书法比赛获奖感言
2014/02/10 职场文书
晨会主持词
2014/03/17 职场文书
青年志愿者活动总结
2014/04/26 职场文书
班级文化建设标语
2014/06/23 职场文书
法人委托书
2014/07/31 职场文书
高中学生会竞选演讲稿
2014/08/25 职场文书
交警失职检讨书
2015/01/26 职场文书
违规违纪检讨书范文
2015/05/06 职场文书
初中教务主任竞聘演讲稿(范文)
2019/08/20 职场文书
深入浅析Django MTV模式
2021/09/04 Python