在python中进行socket通信

socket是计算机通信中常常使用到的一种通信技术。本文介绍如何在python中使用这一方法在多个进程之间进行通信。

Client

作为客户端,只需要知道服务器的地址与端口,发送请求,接收数据即可,并不需要非常复杂的操作。

示例1

以访问新浪微博的主页为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 导入socket库:
import socket
# 创建一个socket:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接:
s.connect(('www.sina.com.cn', 80))
# 发送数据:
s.send('GET / HTTP/1.1\r\nHost: www.sina.com.cn\r\nConnection: close\r\n\r\n')
# 接收数据:
buffer = []
while True:
# 每次最多接收1k字节:
d = s.recv(1024)
if d:
buffer.append(d)
else:
break
data = ''.join(buffer)
s.close()

接收数据时,调用recv(max)方法,一次最多接收指定的字节数,因此,在一个while循环中反复接收,直到recv()返回空数据,表示接收完毕,退出循环。。当我们接收完数据后,调用close()方法关闭Socket,这样,一次完整的网络通信就结束了。

示例2

接收并解码json数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import socket
import time
import json
import numpy as np
import matplotlib.pyplot as plt

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 9999))
print s.recv(1024)
t=time.time()
s.send('a')
data_rec=s.recv(400000)
print(time.time()-t)
s.send('exit')
s.close()
print(len(data_rec))
J=json.loads(data_rec)
I=J[0]['img']
I=np.asarray(I)
plt.imshow(I)
plt.show()

这里json数据中有3个列表元素,每个元素是一个字典,字典的键是image,对应的值是图片矩阵。
注意这里是在本机上进行通讯,为了方便起见返回值最大设置为400000字节。

Server

这里给出服务器端的代码实现:

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
import socket
import threading
import json
import time
import numpy as np


def tcplink(sock, addr):
print 'Accept new connection from %s:%s...' % addr
sock.send('Welcome!')

while True:
x = []
for i in range(3):
d = {}
I = np.random.rand(64, 64)
d['img'] = I.tolist()
x.append(d)
# print(x)
J = json.dumps(x)
data = sock.recv(1024)
# time.sleep(1)
if data == 'exit' or not data:
break
sock.send(J)
sock.close()
print 'Connection from %s:%s closed.' % addr

if __name__ == '__main__':
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('0.0.0.0', 9999))
s.listen(5)
print 'Waiting for connection...'
while True:
sock, addr = s.accept()
t = threading.Thread(target=tcplink, args=(sock, addr))
t.start()

s.bind(('0.0.0.0', 9999))指定服务器的端口和ip,127.0.0.1表示只在本机内部通信,0.0.0.0表示在所有网卡上设置端口,可以由外部进行访问。
s.listen(5) 队列中最多允许5个请求,超过五个请求时会拒绝后面的请求。
sock, addr = s.accept()返回请求的socket和地址,注意accept函数默认是阻塞型的,会一直等待直到接收到请求才返回值,因此这里while True循环中不需要费心考虑太多。
t = threading.Thread(target=tcplink, args=(sock, addr))另外开启一个线程处理请求。
sock.send(J)处理好要发送的数据进行发送。