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列表与元组详解实例
Nov 01 Python
python聊天程序实例代码分享
Nov 18 Python
Python中asyncore异步模块的用法及实现httpclient的实例
Jun 28 Python
python+selenium实现简历自动刷新的示例代码
May 20 Python
解决Python3 抓取微信账单信息问题
Jul 19 Python
python中的列表与元组的使用
Aug 08 Python
Python tkinter实现图片标注功能(完整代码)
Dec 08 Python
python框架Django实战商城项目之工程搭建过程图文详解
Mar 09 Python
带你学习Python如何实现回归树模型
Jul 16 Python
python+requests实现接口测试的完整步骤
Oct 27 Python
golang中的空接口使用详解
Mar 30 Python
python套接字socket通信
Apr 01 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语言中global和$GLOBALS[]的分析 之二
2012/02/02 PHP
解析php利用正则表达式解决采集内容排版的问题
2013/06/20 PHP
浅谈COOKIE和SESSION区别
2015/07/19 PHP
JavaScript 图像动画的小demo
2012/05/23 Javascript
当前页禁止复制粘贴截屏代码小集
2013/07/24 Javascript
javascript定义变量时带var与不带var的区别分析
2015/01/12 Javascript
JS实现两表格里数据来回转移的方法
2015/05/28 Javascript
Javascript实现div层渐隐效果的方法
2015/05/30 Javascript
js显示当前日期时间和星期几
2015/10/22 Javascript
微信小程序 for 循环详解
2016/10/09 Javascript
基于jQuery实现火焰灯效果导航菜单
2017/01/04 Javascript
详解vuejs之v-for列表渲染
2017/06/22 Javascript
基于bootstrap实现多个下拉框同时搜索功能
2017/07/19 Javascript
详解webpack中的hash、chunkhash、contenthash区别
2018/01/05 Javascript
angularjs实现的购物金额计算工具示例
2018/05/08 Javascript
详解JS函数stack size计算方法
2018/06/18 Javascript
vue 权限认证token的实现方法
2018/07/17 Javascript
JavaScript中toLocaleString()和toString()的区别实例分析
2018/08/14 Javascript
解决layui前端框架 form表单,table表等内置控件不显示的问题
2018/08/19 Javascript
vue组件tabbar使用方法详解
2018/11/06 Javascript
使用Layui搭建后台管理界面的操作方法
2019/09/20 Javascript
Javascript异步编程async实现过程详解
2020/04/02 Javascript
用python登录Dr.com思路以及代码分享
2014/06/25 Python
Tensorflow使用支持向量机拟合线性回归
2018/09/07 Python
Python3实现爬虫爬取赶集网列表功能【基于request和BeautifulSoup模块】
2018/12/05 Python
Python Subprocess模块原理及实例
2019/08/26 Python
python ftplib模块使用代码实例
2019/12/31 Python
Django缓存Cache使用详解
2020/11/30 Python
详解如何用canvas画一个微笑的表情
2019/03/14 HTML / CSS
香港时装购物网站:ZALORA香港
2017/04/23 全球购物
expedia比利时:预订航班+酒店并省钱
2018/07/13 全球购物
英国DIY和家居装饰领域的主要品牌:Wickes
2019/11/26 全球购物
一道写SQL的面试题和答案
2013/11/19 面试题
UML设计模式笔试题
2014/06/07 面试题
主要的Ajax框架都有什么
2013/11/14 面试题
网络信息管理员岗位职责
2014/01/05 职场文书