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的Tornado框架实现一个简单的WebQQ机器人
Apr 24 Python
在python的类中动态添加属性与生成对象
Sep 17 Python
python的random模块及加权随机算法的python实现方法
Jan 04 Python
Django使用httpresponse返回用户头像实例代码
Jan 26 Python
Python实现去除列表中重复元素的方法小结【4种方法】
Apr 27 Python
使用 Python 实现微信群友统计器的思路详解
Sep 26 Python
用pycharm开发django项目示例代码
Jun 13 Python
python 实现分组求和与分组累加求和代码
May 18 Python
Python参数传递机制传值和传引用原理详解
May 22 Python
Python flask框架端口失效解决方案
Jun 04 Python
python实现对doc、txt、xls等文档的读写操作
Apr 02 Python
Python使用pandas导入csv文件内容的示例代码
Dec 24 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
用Zend Encode编写开发PHP程序
2006/10/09 PHP
php+ajax实现文章自动保存的方法
2014/12/30 PHP
php生成gif动画的方法
2015/11/05 PHP
PHP+JS三级菜单联动菜单实现方法
2016/02/24 PHP
PHP创建单例后台进程的方法示例
2017/05/23 PHP
PHP在同一域名下两个不同的项目做独立登录机制详解
2017/09/22 PHP
求解开jscript.encode代码的asp函数
2007/02/28 Javascript
JavaScript中的Screen屏幕对象
2008/01/16 Javascript
JavaScript显示表单内元素数量的方法
2015/04/02 Javascript
javascript显示倒计时控制按钮的简单实现
2016/06/07 Javascript
vue-router3.0版本中 router.push 不能刷新页面的问题
2018/05/10 Javascript
Node.js中你不可不精的Stream(流)
2018/06/08 Javascript
使用setup.py安装python包和卸载python包的方法
2013/11/27 Python
python实现apahce网站日志分析示例
2014/04/02 Python
Python的装饰器模式与面向切面编程详解
2015/06/21 Python
Python编程之event对象的用法实例分析
2017/03/23 Python
Python和C/C++交互的几种方法总结
2017/05/11 Python
Python tkinter模块弹出窗口及传值回到主窗口操作详解
2017/07/28 Python
python实现蒙特卡罗方法教程
2019/01/28 Python
python向字符串中添加元素的实例方法
2019/06/28 Python
Python实现Mysql数据统计及numpy统计函数
2019/07/15 Python
python 的 scapy库,实现网卡收发包的例子
2019/07/23 Python
django多对多表的创建,级联删除及手动创建第三张表
2019/07/25 Python
使用selenium和pyquery爬取京东商品列表过程解析
2019/08/15 Python
Python实现微信中找回好友、群聊用户撤回的消息功能示例
2019/08/23 Python
使用浏览器访问python写的服务器程序
2019/10/10 Python
Python importlib动态导入模块实现代码
2020/04/16 Python
使用darknet框架的imagenet数据分类预训练操作
2020/07/07 Python
Python字符串函数strip()原理及用法详解
2020/07/23 Python
Django-Scrapy生成后端json接口的方法示例
2020/10/06 Python
Guess美国官网:美国知名服装品牌
2019/04/08 全球购物
教师旷工检讨书
2014/01/18 职场文书
《灰椋鸟》教学反思
2014/04/27 职场文书
工业设计专业自荐书
2014/06/05 职场文书
总账会计岗位职责
2015/04/02 职场文书
2015大一新生军训感言
2015/08/01 职场文书