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编码时应该注意的几个情况
Mar 04 Python
python计算圆周长、面积、球体体积并画出圆
Apr 08 Python
如何在Python中编写并发程序
Feb 27 Python
Python 递归函数详解及实例
Dec 27 Python
基于Python的文件类型和字符串详解
Dec 21 Python
python正则实现提取电话功能
Feb 24 Python
python 正则表达式贪婪模式与非贪婪模式原理、用法实例分析
Oct 14 Python
在keras里面实现计算f1-score的代码
Jun 15 Python
Python+Opencv身份证号码区域提取及识别实现
Aug 25 Python
Python离线安装各种库及pip的方法
Nov 28 Python
python实现自定义日志的具体方法
May 28 Python
Python编程源码报错解决方法总结经验分享
Oct 05 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版(2)
2006/10/09 PHP
不错的PHP学习之php4与php5之间会穿梭一点点感悟
2007/05/03 PHP
destoon实现会员商铺中指定会员或会员组投放广告的方法
2014/08/21 PHP
php中json_encode不兼容JSON_UNESCAPED_UNICODE的解决方案
2016/05/31 PHP
关于JavaScript的gzip静态压缩方法
2007/01/05 Javascript
js 事件小结 表格区别
2007/08/13 Javascript
为超链接加上disabled后的故事
2010/12/10 Javascript
左右悬浮可分组的网站QQ在线客服代码(可谓经典)
2012/12/21 Javascript
javascript实现根据iphone屏幕方向调用不同样式表的方法
2015/07/13 Javascript
XML、HTML、CSS与JS的区别整理
2016/02/18 Javascript
easyui window refresh 刷新两次的解决方法(推荐)
2016/05/18 Javascript
基于Bootstrap的Metronic框架实现条码和二维码的生成及打印处理操作
2016/08/29 Javascript
Vue.js第三天学习笔记(计算属性computed)
2016/12/01 Javascript
Parcel.js + Vue 2.x 极速零配置打包体验教程
2017/12/24 Javascript
一步一步实现Vue的响应式(对象观测)
2019/09/02 Javascript
JS实现旋转木马轮播图
2020/01/01 Javascript
es6数组之扩展运算符操作实例分析
2020/04/25 Javascript
微信小程序转化为uni-app项目的方法示例
2020/05/22 Javascript
Python中运行并行任务技巧
2015/02/26 Python
Python数据分析之双色球中蓝红球分析统计示例
2018/02/03 Python
Python中列表与元组的乘法操作示例
2018/02/10 Python
opencv与numpy的图像基本操作
2019/03/08 Python
详解Python读取yaml文件多层菜单
2019/03/23 Python
Python PIL读取的图像发生自动旋转的实现方法
2019/07/05 Python
Django密码存储策略分析
2020/01/09 Python
python numpy数组中的复制知识解析
2020/02/03 Python
Python logging自定义字段输出及打印颜色
2020/11/30 Python
Python 虚拟环境工作原理解析
2020/12/24 Python
CSS3 icon font完全指南(CSS3 font 会取代icon图标)
2013/01/06 HTML / CSS
致长跑运动员广播稿
2014/01/31 职场文书
公益广告语集锦
2014/03/13 职场文书
岗位说明书怎么写
2014/07/30 职场文书
2016年党员学习廉政准则心得体会
2016/01/20 职场文书
人事行政部各岗位职责说明书!
2019/07/15 职场文书
MySQL 角色(role)功能介绍
2021/04/24 MySQL
详解Java线程池是如何重复利用空闲线程的
2021/06/26 Java/Android