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 06 Python
Python中使用PyHook监听鼠标和键盘事件实例
Jul 18 Python
Python端口扫描简单程序
Nov 10 Python
Python实现简易端口扫描器代码实例
Mar 15 Python
Python使用sorted排序的方法小结
Jul 28 Python
Python实现将json文件中向量写入Excel的方法
Mar 26 Python
pandas每次多Sheet写入文件的方法
Dec 10 Python
Python线性拟合实现函数与用法示例
Dec 13 Python
python 日期排序的实例代码
Jul 11 Python
Django Aggregation聚合使用方法解析
Aug 01 Python
Python高阶函数与装饰器函数的深入讲解
Nov 10 Python
对Keras自带Loss Function的深入研究
May 25 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创建多级目录代码
2008/06/05 PHP
php5.3 废弃函数小结
2010/05/16 PHP
PHP动态页生成静态页的3种常用方法
2014/11/13 PHP
jQuery+PHP实现的掷色子抽奖游戏实例
2015/01/04 PHP
php格式化时间戳
2016/12/17 PHP
thinkphp5 URL和路由的功能详解与实例
2017/12/26 PHP
php解析非标准json、非规范json的方式实例
2020/12/10 PHP
IE autocomplete internet explorer's autocomplete
2007/06/30 Javascript
JavaScript写的一个DIV 弹出网页对话框
2009/08/14 Javascript
Jquery给基本控件的取值、赋值示例
2014/05/23 Javascript
实例详解Nodejs 保存 payload 发送过来的文件
2016/01/14 NodeJs
jQuery.parseHTML() 函数详解
2017/01/09 Javascript
mac上node.js环境的安装测试
2017/07/03 Javascript
ReactNative短信验证码倒计时控件的实现代码
2017/07/20 Javascript
利用node.js爬取指定排名网站的JS引用库详解
2017/07/25 Javascript
利用JavaScript实现栈的数据结构示例代码
2017/08/02 Javascript
解决vue的 v-for 循环中图片加载路径问题
2018/09/03 Javascript
详解Vue iview IE浏览器不兼容报错(Iview Bable polyfill)
2019/01/07 Javascript
微信小程序实现分享商品海报功能
2019/09/30 Javascript
Vue3.x源码调试的实现方法
2019/10/13 Javascript
django中的setting最佳配置小结
2017/11/21 Python
Python获取指定文件夹下的文件名的方法
2018/02/06 Python
django框架实现一次性上传多个文件功能示例【批量上传】
2019/06/19 Python
对python中UDP,socket的使用详解
2019/08/22 Python
virtualenv介绍及简明教程
2020/06/23 Python
Python限制内存和CPU使用量的方法(Unix系统适用)
2020/08/04 Python
Selenium alert 弹窗处理的示例代码
2020/08/06 Python
HTML5添加鼠标悬浮音响效果不使用FLASH
2014/04/23 HTML / CSS
Dr. Martens马汀博士德国官网:马丁靴鼻祖
2019/12/26 全球购物
金属材料工程个人求职的自我评价
2013/12/04 职场文书
50岁生日感言
2014/01/23 职场文书
竞选学生会演讲稿
2014/04/25 职场文书
竞选班干部演讲稿100字
2014/08/20 职场文书
迟到检讨书2000字(精选篇)
2014/10/07 职场文书
外贸采购员岗位职责
2015/04/03 职场文书
2015学校六五普法工作总结
2015/04/22 职场文书