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中元祖、列表和字典的区别
Aug 17 Python
Python实现扣除个人税后的工资计算器示例
Mar 26 Python
python 读取目录下csv文件并绘制曲线v111的方法
Jul 06 Python
对python csv模块配置分隔符和引用符详解
Dec 12 Python
Python脚本按照当前日期创建多级目录
Mar 01 Python
cProfile Python性能分析工具使用详解
Jul 22 Python
基于python框架Scrapy爬取自己的博客内容过程详解
Aug 05 Python
pytorch 获取层权重,对特定层注入hook, 提取中间层输出的方法
Aug 17 Python
Django之使用内置函数和celery发邮件的方法示例
Sep 16 Python
python如何将图片转换素描画
Sep 08 Python
python如何绘制疫情图
Sep 16 Python
python 用Matplotlib作图中有多个Y轴
Nov 28 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
15种PHP Encoder的比较
2007/04/17 PHP
php foreach 参数强制类型转换的问题
2010/12/10 PHP
解析PHP中如何将数组变量写入文件
2013/06/06 PHP
php-fpm添加service服务的例子
2018/04/27 PHP
PHP simplexml_load_string()函数实例讲解
2019/02/03 PHP
在JavaScript中遭遇级联表达式陷阱
2007/03/08 Javascript
JS getMonth()日期函数的值域是0-11
2010/02/15 Javascript
js变量、作用域及内存详解
2014/09/23 Javascript
jQuery实现垂直半透明手风琴特效代码分享
2015/08/21 Javascript
向JavaScript的数组中添加元素的方法小结
2015/10/24 Javascript
JavaScript优化专题之Loading and Execution加载和运行
2016/01/20 Javascript
javascript每日必学之基础入门
2016/02/16 Javascript
jQuery on()方法绑定动态元素的点击事件实例代码浅析
2016/06/16 Javascript
详解vue 实例方法和数据
2017/10/23 Javascript
浅谈v-for 和 v-if 并用时筛选条件方法
2019/11/07 Javascript
jquery实现上传文件进度条
2020/03/26 jQuery
Node.js设置定时任务之node-schedule模块的使用详解
2020/04/28 Javascript
jQuery cookie的公共方法封装和使用示例
2020/06/01 jQuery
Vue Render函数原理及代码实例解析
2020/07/30 Javascript
python文件和目录操作方法大全(含实例)
2014/03/12 Python
python自然语言编码转换模块codecs介绍
2015/04/08 Python
Python面向对象编程基础解析(一)
2017/10/26 Python
Python openpyxl模块原理及用法解析
2020/01/19 Python
Python守护进程实现过程详解
2020/02/10 Python
Python任务调度模块APScheduler使用
2020/04/15 Python
keras 获取某层的输入/输出 tensor 尺寸操作
2020/06/10 Python
opencv 图像加法与图像融合的实现代码
2020/07/08 Python
Monki官网:斯堪的纳维亚的独立时尚品牌
2020/11/09 全球购物
奥林匹亚体育:Olympia Sports
2020/12/30 全球购物
小学生竞选班长演讲稿
2014/04/24 职场文书
暑期社会实践先进个人主要事迹
2014/05/22 职场文书
五好关工委申报材料
2014/05/31 职场文书
员工三分钟演讲稿
2014/08/19 职场文书
2015年小学二年级班主任工作总结
2015/05/21 职场文书
2015年行政管理人员工作总结
2015/10/15 职场文书
Python 使用 Frame tkraise() 方法在 Tkinter 应用程序中的Frame之间切换
2022/04/24 Python