服务器:#server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
#!/usr/bin/env python
#-*-coding:utf-8-*-
import sys
import struct #将字符串打包为二进制流进行网络传输
import select #
import signal #用于捕获中断信号
import cPickle #将python对象进行序列化:dumps将python对象序列化保存为字符串,loads与之相反
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
#!/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实现多对多全双工通信的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/zhidetian/article/details/53470849