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下使用状态机的教程
Apr 11 Python
python编写简单爬虫资料汇总
Mar 22 Python
Python生成随机密码的方法
Jun 16 Python
Python语言实现百度语音识别API的使用实例
Dec 13 Python
Python3实现发送QQ邮件功能(附件)
Dec 23 Python
django框架事务处理小结【ORM 事务及raw sql,customize sql 事务处理】
Jun 27 Python
Python collections中的双向队列deque简单介绍详解
Nov 04 Python
Tensorflow分批量读取数据教程
Feb 07 Python
Pandas时间序列基础详解(转换,索引,切片)
Feb 26 Python
浅谈python的elementtree模块处理中文注意事项
Mar 06 Python
Numpy 多维数据数组的实现
Jun 18 Python
Windows下pycharm安装第三方库失败(通用解决方案)
Sep 17 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中使用PDF文档功能
2006/10/09 PHP
php生成随机密码的三种方法小结
2010/09/04 PHP
Yii分页用法实例详解
2014/12/04 PHP
[原创]php简单防盗链验证实现方法
2016/07/09 PHP
PHP实现验证码校验功能
2017/11/16 PHP
用JavaScript脚本实现Web页面信息交互
2006/10/11 Javascript
改变隐藏的input中value的值代码
2013/12/30 Javascript
javaScript的函数对象的声明详解
2015/02/06 Javascript
jQuery选择器源码解读(一):Sizzle方法
2015/03/31 Javascript
jQuery实现手机号码输入提示功能实例
2015/04/30 Javascript
使用coffeescript编写node.js项目的方法汇总
2015/08/05 Javascript
学习掌握JavaScript中this的使用技巧
2016/08/29 Javascript
js实现非常棒的弹出div
2016/10/06 Javascript
JavaScript中localStorage对象存储方式实例分析
2017/01/12 Javascript
利用Vue.js实现checkbox的全选反选效果
2017/01/18 Javascript
Vue源码学习之初始化模块init.js解析
2017/11/02 Javascript
代码详解javascript模块加载器
2018/03/04 Javascript
在vue中使用v-bind:class的选项卡方法
2018/09/27 Javascript
详解如何webpack使用DllPlugin
2018/09/30 Javascript
layui 表格操作列按钮动态显示的实现方法
2019/09/06 Javascript
vue中get请求如何传递数组参数的方法示例
2019/11/08 Javascript
jQuery实现图片切换效果
2020/10/19 jQuery
浅谈python中的__init__、__new__和__call__方法
2017/07/18 Python
在Python程序员面试中被问的最多的10道题
2017/12/05 Python
Python进阶之自定义对象实现切片功能
2019/01/07 Python
使用Python向DataFrame中指定位置添加一列或多列的方法
2019/01/29 Python
Python读取stdin方法实例
2019/05/24 Python
django 实现将本地图片存入数据库,并能显示在web上的示例
2019/08/07 Python
python判断一个变量是否已经设置的方法
2020/08/13 Python
天巡全球:Skyscanner Global
2017/06/20 全球购物
会计实习生自我鉴定
2013/12/12 职场文书
新任教师自我鉴定
2014/02/24 职场文书
三提三创主题教育活动查摆整改措施
2014/10/25 职场文书
2014年体检中心工作总结
2014/12/23 职场文书
小学语文继续教育研修日志
2015/11/13 职场文书
Django框架中表单的用法
2022/06/10 Python