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 urllib模块urlopen()与urlretrieve()详解
Nov 01 Python
python正则表达式判断字符串是否是全部小写示例
Dec 25 Python
使用scrapy实现爬网站例子和实现网络爬虫(蜘蛛)的步骤
Jan 23 Python
python实现从web抓取文档的方法
Sep 26 Python
简单的Python抓taobao图片爬虫
Oct 26 Python
Python获取Linux系统下的本机IP地址代码分享
Nov 07 Python
Python实现批量下载图片的方法
Jul 08 Python
教大家使用Python SqlAlchemy
Feb 12 Python
Python数据类型详解(一)字符串
May 08 Python
Kears 使用:通过回调函数保存最佳准确率下的模型操作
Jun 17 Python
Python爬虫逆向分析某云音乐加密参数的实例分析
Dec 04 Python
OpenCV绘制圆端矩形的示例代码
Aug 30 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
fleaphp crud操作之find函数的使用方法
2011/04/23 PHP
PHPThumb图片处理实例
2014/05/03 PHP
php用户注册时常用的检验函数实例总结
2014/12/22 PHP
document.body.scrollTop 值总为0的解决方法 比较常见的标准问题
2009/11/30 Javascript
基于jQuery的消息提示插件 DivAlert之旅(二)
2010/04/01 Javascript
Jquery 插件开发笔记整理
2011/01/17 Javascript
基于jQuery的让非HTML5浏览器支持placeholder属性的代码
2011/05/24 Javascript
Jquery Uploadify多文件上传带进度条且传递自己的参数
2013/08/28 Javascript
jQuery取消ajax请求的方法
2015/06/09 Javascript
深入理解Javascript中的valueOf与toString
2017/01/04 Javascript
Node.js服务器开启Gzip压缩教程
2017/08/11 Javascript
Node.js log4js日志管理详解
2018/07/31 Javascript
vue 使用vue-i18n做全局中英文切换的方法
2018/10/29 Javascript
跨域请求两种方法 jsonp和cors的实现
2018/11/11 Javascript
实例讲解React 组件
2020/07/07 Javascript
[00:50]深扒TI7聊天轮盘语音出处6
2017/05/11 DOTA
python中执行shell命令的几个方法小结
2014/09/18 Python
轻松实现python搭建微信公众平台
2016/02/16 Python
python实现多线程的方式及多条命令并发执行
2016/06/07 Python
Python 专题四 文件基础知识
2017/03/20 Python
Django objects的查询结果转化为json的三种方式的方法
2018/11/07 Python
python实现的读取网页并分词功能示例
2019/10/29 Python
使用已经得到的keras模型识别自己手写的数字方式
2020/06/29 Python
python 基于opencv 实现一个鼠标绘图小程序
2020/12/11 Python
python获取天气接口给指定微信好友发天气预报
2020/12/28 Python
生产车间实习自我鉴定
2013/09/23 职场文书
现役军人家属慰问信
2015/03/24 职场文书
单位推荐信范文
2015/03/27 职场文书
2015年结对帮扶工作总结
2015/05/04 职场文书
小学语文教师研修日志
2015/11/13 职场文书
会议开幕致辞怎么写
2016/03/03 职场文书
简历自我评价范文
2019/04/24 职场文书
CSS 文字装饰 text-decoration & text-emphasis 详解
2021/04/06 HTML / CSS
Mysql 用户权限管理实现
2021/05/25 MySQL
html5实现点击弹出图片功能
2021/07/16 HTML / CSS
Redis批量生成数据的实现
2022/06/05 Redis