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实现的最近最少使用算法
Jul 10 Python
Python实现多线程抓取妹子图
Aug 08 Python
Python实现代码统计工具(终极篇)
Jul 04 Python
python去除字符串中的换行符
Oct 11 Python
python批量下载抖音视频
Jun 17 Python
anaconda中更改python版本的方法步骤
Jul 14 Python
浅谈TensorFlow中读取图像数据的三种方式
Jun 30 Python
Python Request类源码实现方法及原理解析
Aug 17 Python
利用python汇总统计多张Excel
Sep 22 Python
pycharm最新激活码有效期至2100年(亲测可用)
Feb 05 Python
Pyhton模块和包相关知识总结
May 12 Python
Python socket如何解析HTTP请求内容
Feb 12 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
Laravel框架生命周期与原理分析
2018/06/12 PHP
yii2.0框架数据库操作简单示例【添加,修改,删除,查询,打印等】
2020/04/13 PHP
javascript 24小时弹出一次的代码(利用cookies)
2009/09/03 Javascript
jQuery中与toggleClass等价的程序段 以及未来学习的方向
2010/03/18 Javascript
js中精确计算加法和减法示例
2014/03/28 Javascript
基于javascript的JSON格式页面展示美化方法
2014/07/02 Javascript
Javascript动态创建div的方法
2015/02/09 Javascript
微信小程序 教程之注册程序
2016/10/17 Javascript
JavaScript实现短信倒计时60s
2017/10/09 Javascript
JS实现调用本地摄像头功能示例
2018/05/18 Javascript
Vue中使用create-keyframe-animation与动画钩子完成复杂动画
2019/04/09 Javascript
全面分析JavaScript 继承
2019/05/30 Javascript
VUE 自定义组件模板的方法详解
2019/08/30 Javascript
Python 除法小技巧
2008/09/06 Python
python引用DLL文件的方法
2015/05/11 Python
Win10下Python环境搭建与配置教程
2016/11/18 Python
对Python进行数据分析_关于Package的安装问题
2017/05/22 Python
python爬虫实战之最简单的网页爬虫教程
2017/08/13 Python
python实现堆和索引堆的代码示例
2018/03/19 Python
Python聊天室程序(基础版)
2018/04/01 Python
基于DataFrame筛选数据与loc的用法详解
2018/05/18 Python
python正则表达式匹配[]中间为任意字符的实例
2018/12/25 Python
PyQt打开保存对话框的方法和使用详解
2019/02/27 Python
基于python使用tibco ems代码实例
2019/12/20 Python
详解python中各种文件打开模式
2020/01/19 Python
Python处理mysql特殊字符的问题
2020/03/02 Python
使用 Python 读取电子表格中的数据实例详解
2020/04/17 Python
Python几种常见算法汇总
2020/06/02 Python
python实现录音功能(可随时停止录音)
2020/10/26 Python
详解Django关于StreamingHttpResponse与FileResponse文件下载的最优方法
2021/01/07 Python
ZWILLING双立人法国网上商店:德国刀具锅具厨具品牌
2019/08/28 全球购物
YSL圣罗兰美妆俄罗斯官网:Yves Saint Lauret RU
2020/09/23 全球购物
大学生毕业求职找工作的自我评价
2013/09/29 职场文书
优秀团员个人的自我评价
2013/10/02 职场文书
导游词之杭州岳王庙
2019/11/13 职场文书
Golang实现AES对称加密的过程详解
2021/05/20 Golang