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使用pyhook监控键盘并实现切换歌曲的功能
Jul 18 Python
wxPython窗口中文乱码解决方法
Oct 11 Python
Python打包文件夹的方法小结(zip,tar,tar.gz等)
Sep 18 Python
Python 模拟登陆的两种实现方法
Aug 10 Python
Python图像处理之识别图像中的文字(实例讲解)
May 10 Python
python3在同一行内输入n个数并用列表保存的例子
Jul 20 Python
Django 实现前端图片压缩功能的方法
Aug 07 Python
pycharm 安装JPype的教程
Aug 08 Python
Python列表删除元素del、pop()和remove()的区别小结
Sep 11 Python
python GUI库图形界面开发之PyQt5打开保存对话框QFileDialog详细使用方法与实例
Feb 27 Python
keras的backend 设置 tensorflow,theano操作
Jun 30 Python
python使用re模块爬取豆瓣Top250电影
Oct 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中逗号与点号的区别
2013/08/05 PHP
微信自定义菜单的处理开发示例
2015/04/16 PHP
php检测mysql表是否存在的方法小结
2017/07/20 PHP
Thinkphp自定义生成缩略图尺寸的方法
2019/08/05 PHP
laravel通过a标签从视图向控制器实现传值
2019/10/15 PHP
jQuery中:selected选择器用法实例
2015/01/04 Javascript
JavaScript实现仿淘宝商品购买数量的增减效果
2016/01/22 Javascript
jquery编写Tab选项卡滚动导航切换特效
2020/07/17 Javascript
微信小程序 火车票查询实例讲解
2016/10/17 Javascript
JS实现复选框的全选和批量删除功能
2017/04/05 Javascript
vue中阻止click事件冒泡,防止触发另一个事件的方法
2018/02/08 Javascript
浅析node应用的timing-attack安全漏洞
2018/02/28 Javascript
vue.js内置组件之keep-alive组件使用
2018/07/10 Javascript
Angular服务Request异步请求的实例讲解
2018/08/13 Javascript
React Component存在的几种形式详解
2018/11/06 Javascript
使用electron制作满屏心特效的示例代码
2018/11/27 Javascript
JavaScript:ES2019 的新特性(译)
2019/08/08 Javascript
[01:17]炒鸡美酒第四天TA暴走
2018/06/05 DOTA
如何解决django配置settings时遇到Could not import settings 'conf.local'
2014/11/18 Python
python获取list下标及其值的简单方法
2016/09/12 Python
DataFrame中去除指定列为空的行方法
2018/04/08 Python
python matplotlib折线图样式实现过程
2019/11/04 Python
Python使用Pandas库常见操作详解
2020/01/16 Python
Python处理mysql特殊字符的问题
2020/03/02 Python
将 Ubuntu 16 和 18 上的 python 升级到最新 python3.8 的方法教程
2020/03/11 Python
Python面向对象程序设计之继承、多态原理与用法详解
2020/03/23 Python
基于Python实现视频的人脸融合功能
2020/06/12 Python
澳大利亚吉他在线:Artist Guitars
2017/03/30 全球购物
香港时装购物网站:ZALORA香港
2017/04/23 全球购物
SmartBuyGlasses荷兰:购买太阳镜和眼镜
2020/03/16 全球购物
领导班子个人查摆问题对照检查材料
2014/10/02 职场文书
2014年为民办实事工作总结
2014/12/20 职场文书
具结保证书
2015/01/17 职场文书
关于童年的读书笔记
2015/06/26 职场文书
幼儿园园长新年寄语
2015/08/17 职场文书
聊一聊python常用的编程模块
2021/05/14 Python