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利用operator模块实现对象的多级排序详解
May 09 Python
Python使用matplotlib绘制余弦的散点图示例
Mar 14 Python
不到20行代码用Python做一个智能聊天机器人
Apr 19 Python
程序员的七夕用30行代码让Python化身表白神器
Aug 07 Python
Python 实现try重新执行
Dec 21 Python
新年福利来一波之Python轻松集齐五福(demo)
Jan 20 Python
python读写文件write和flush的实现方式
Feb 21 Python
Python第三方包PrettyTable安装及用法解析
Jul 08 Python
基于opencv的selenium滑动验证码的实现
Jul 24 Python
Python filter()及reduce()函数使用方法解析
Sep 05 Python
python 检测nginx服务邮件报警的脚本
Dec 31 Python
python爬取2021猫眼票房字体加密实例
Feb 19 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 随机排序广告的实现代码
2011/05/09 PHP
php中可能用来加密字符串的函数[base64_encode、urlencode、sha1]
2012/01/16 PHP
通过table标签,PHP输出EXCEL的实现方法
2013/07/24 PHP
PHP中session变量的销毁
2014/02/27 PHP
php调用nginx的mod_zip模块打包ZIP文件
2014/06/11 PHP
destoon二次开发常用数据库操作
2014/06/21 PHP
destoon文章模块调用企业会员资料的方法
2014/08/22 PHP
php微信开发自定义菜单
2016/08/27 PHP
PHP预定义超全局数组变量小结
2018/08/20 PHP
Laravel学习笔记之Artisan命令生成自定义模板的方法
2018/11/22 PHP
PHP查找一列有序数组是否包含某值的方法
2020/02/07 PHP
jQuery函数的等价原生函数代码示例
2013/05/27 Javascript
使用Chart.js图表库制作漂亮的响应式表单
2015/10/28 Javascript
js 发布订阅模式的实例讲解
2017/09/10 Javascript
详解Vue中数组和对象更改后视图不刷新的问题
2018/09/21 Javascript
如何实现双向绑定mvvm的原理实现
2019/05/28 Javascript
微信小程序下拉加载和上拉刷新两种实现方法详解
2019/09/05 Javascript
0基础学习前端开发的一些建议
2020/07/14 Javascript
vue 封装面包屑组件教程
2020/11/16 Javascript
python实现的二叉树算法和kmp算法实例
2014/04/25 Python
Python实现的飞速中文网小说下载脚本
2015/04/23 Python
python 编写简单网页服务器的实例
2018/06/01 Python
用python3教你任意Html主内容提取功能
2018/11/05 Python
对Python3中dict.keys()转换成list类型的方法详解
2019/02/03 Python
利用ctypes获取numpy数组的指针方法
2019/02/12 Python
基于python解线性矩阵方程(numpy中的matrix类)
2019/10/21 Python
python中图像通道分离与合并实例
2020/01/17 Python
Python发起请求提示UnicodeEncodeError错误代码解决方法
2020/04/21 Python
keras 回调函数Callbacks 断点ModelCheckpoint教程
2020/06/18 Python
Python-openCV开运算实例
2020/07/05 Python
python 制作磁力搜索工具
2021/03/04 Python
卡骆驰新加坡官网:Crocs新加坡
2018/06/12 全球购物
三万活动总结
2014/04/28 职场文书
个人委托书范本汇总
2014/10/01 职场文书
党员志愿者服务倡议书
2015/04/29 职场文书
家长反馈意见及建议
2015/06/03 职场文书