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访问纯真IP数据库的代码
May 19 Python
pycharm 使用心得(一)安装和首次使用
Jun 05 Python
Python利用Beautiful Soup模块创建对象详解
Mar 27 Python
Python三种遍历文件目录的方法实例代码
Jan 19 Python
win10下tensorflow和matplotlib安装教程
Sep 19 Python
python实现归并排序算法
Nov 22 Python
python存储16bit和32bit图像的实例
Dec 05 Python
不到20行代码用Python做一个智能聊天机器人
Apr 19 Python
Python for循环及基础用法详解
Nov 08 Python
Python语言异常处理测试过程解析
Jan 08 Python
python实现在线翻译
Jun 18 Python
基于PyTorch的permute和reshape/view的区别介绍
Jun 18 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采集类Snoopy抓取图片实例
2014/06/19 PHP
解析PHP的Yii框架中cookie和session功能的相关操作
2016/03/17 PHP
Mac下快速搭建PHP开发环境步骤详解
2019/05/05 PHP
PHP设计模式之建造者模式(Builder)原理与用法案例详解
2019/12/12 PHP
Javascript执行效率全面总结
2013/11/04 Javascript
JavaScript学习笔记之Cookie对象
2015/01/22 Javascript
JavaScript日期时间与时间戳的转换函数分享
2015/01/31 Javascript
JS前端加密算法示例
2016/12/22 Javascript
Bootstrap3 图片(响应式图片&amp;图片形状)
2017/01/04 Javascript
Bootstrap提示框效果的实例代码
2017/07/12 Javascript
bootstrap table服务端实现分页效果
2017/08/10 Javascript
微信小程序实现长按删除图片的示例
2018/05/18 Javascript
JS实现把一个页面层数据传递到另一个页面的两种方式
2018/08/13 Javascript
H5+C3+JS实现五子棋游戏(AI篇)
2020/05/28 Javascript
js中位数不足自动补位扩展padLeft、padRight实现代码
2020/04/06 Javascript
微信小程序个人中心的列表控件实现代码
2020/04/26 Javascript
基于Vue sessionStorage实现保留搜索框搜索内容
2020/06/01 Javascript
Vue使用Three.js加载glTF模型的方法详解
2020/06/14 Javascript
[01:01:51]EG vs VG Supermajor小组赛B组 BO3 第二场 6.2
2018/06/03 DOTA
Python strip lstrip rstrip使用方法
2008/09/06 Python
一文总结学习Python的14张思维导图
2017/10/17 Python
windows下添加Python环境变量的方法汇总
2018/05/14 Python
解决Python spyder显示不全df列和行的问题
2020/04/20 Python
Python多线程:主线程等待所有子线程结束代码
2020/04/25 Python
pycharm无法安装第三方库的问题及解决方法以scrapy为例(图解)
2020/05/09 Python
python如何调用百度识图api
2020/09/29 Python
canvas粒子动画背景的实现示例
2018/09/03 HTML / CSS
HTML5 绘制图像(上)之:关于canvas元素引领下一代web页面的问题
2013/04/24 HTML / CSS
随机分配座位,共50个学生,使学号相邻的同学座位不能相邻
2014/01/18 面试题
成考报名单位证明范本
2014/01/16 职场文书
应聘医药销售自荐书范文
2014/02/08 职场文书
2014年庆祝国庆65周年演讲稿
2014/09/21 职场文书
企业领导班子四风对照检查材料
2014/09/27 职场文书
警告通知
2015/04/25 职场文书
nginx配置文件使用环境变量的操作方法
2021/06/02 Servers
一定要知道的 25 个 Vue 技巧
2021/11/02 Vue.js