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 相关文章推荐
python3编写C/S网络程序实例教程
Aug 25 Python
Python生成器(Generator)详解
Apr 13 Python
连接Python程序与MySQL的教程
Apr 29 Python
Python中使用ElementTree解析XML示例
Jun 02 Python
详解Python操作RabbitMQ服务器消息队列的远程结果返回
Jun 30 Python
python爬取网页内容转换为PDF文件
Jul 28 Python
Python数据持久化shelve模块用法分析
Jun 29 Python
Flask之flask-script模块使用
Jul 26 Python
Python高级特性之闭包与装饰器实例详解
Nov 19 Python
Python求解排列中的逆序数个数实例
May 03 Python
python判断变量是否为列表的方法
Sep 17 Python
Python Django搭建文件下载服务器的实现
May 10 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生成HTML静态页面实例代码
2008/08/31 PHP
php获取服务器端mac和客户端mac的地址支持WIN/LINUX
2014/05/15 PHP
PHP实现的浏览器检查类
2016/04/11 PHP
浅谈PHP的数据库接口和技术
2016/12/09 PHP
游戏人文件夹程序 ver 4.03
2006/07/14 Javascript
JavaScript 事件查询综合
2009/07/13 Javascript
制作高质量的JQuery Plugin 插件的方法
2010/04/20 Javascript
jQuery EasyUI API 中文文档 - TimeSpinner时间微调器
2011/10/23 Javascript
nullJavascript中创建对象的五种方法实例
2013/05/07 Javascript
jquery实现侧边弹出的垂直导航
2014/12/09 Javascript
分析了一下JQuery中的extend方法实现原理
2015/02/27 Javascript
BootStrap3学习笔记(一)之网格系统
2016/05/20 Javascript
浅谈js中子页面父页面方法 变量相互调用
2016/08/04 Javascript
js初始化验证实例详解
2016/11/26 Javascript
JS新包管理工具yarn和npm的对比与使用入门
2016/12/09 Javascript
Javascript 使用ajax与C#获取文件大小实例详解
2017/01/13 Javascript
AngularJs中 ng-repeat指令中实现含有自定义指令的动态html的方法
2017/01/19 Javascript
jQuery插件HighCharts绘制2D带Label的折线图效果示例【附demo源码下载】
2017/03/08 Javascript
对于Javascript 执行上下文的全面了解
2017/09/05 Javascript
Express + Session 实现登录验证功能
2017/09/08 Javascript
react.js 父子组件数据绑定实时通讯的示例代码
2017/09/25 Javascript
纯JS实现出生日期[年月日]下拉菜单效果
2018/06/01 Javascript
Redux实现组合计数器的示例代码
2018/07/04 Javascript
CentOS安装pillow报错的解决方法
2016/01/27 Python
Python编程中归并排序算法的实现步骤详解
2016/05/04 Python
Python判断某个用户对某个文件的权限
2016/10/13 Python
Python实现解析Bit Torrent种子文件内容的方法
2017/08/29 Python
详解python实现交叉验证法与留出法
2019/07/11 Python
HTML5中的新元素介绍
2008/10/17 HTML / CSS
创造美妙香氛体验:Aera扩散器和香水
2018/11/25 全球购物
Quiksilver荷兰官方网站:冲浪和滑雪板
2019/11/16 全球购物
Steiff台湾官网:德国金耳釦泰迪熊
2019/12/26 全球购物
我能否用void** 指针作为参数, 使函数按引用接受一般指针
2013/02/16 面试题
软件工程师岗位职责
2013/11/16 职场文书
教师党的群众路线教育实践活动个人整改措施
2014/11/04 职场文书
JS实现九宫格拼图游戏
2022/06/28 Javascript