服务器:#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