python

超轻量级php框架startmvc

Python socket实现多对多全双工通信的方法

更新时间:2020-06-24 08:12:01 作者:startmvc
服务器:#server.py#!/usr/bin/envpython#-*-coding:utf-8-*-importsysimportstruct#将字符串打包为二进制流进

服务器:#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 socket 全双工 通信