Python · 网络编程

简介

用 TCP 协议进行 Socket 编程在 Python 中十分简单,对于客户端,要主动连接服务器的 IP 和指定端口,对于服务器,要首先监听指定端口,然后,对每一个新的连接,创建一个线程或进程来处理。通常,服务器程序会无限运行下去。同一个端口,被一个 Socket 绑定了以后,就不能被别的 Socket 绑定了。

TCP编程

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/python
# -*- coding:utf-8 -*-
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接:
s.connect(('127.0.0.1', 9999))
# 接收欢迎消息:
print(s.recv(1024).decode('utf-8'))
for data in [b'Michael', b'Tracy', b'Sarah']:
# 发送数据:
s.send(data)
print(s.recv(1024).decode('utf-8'))
s.send(b'exit')
s.close()

服务端

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
#!/usr/bin/python
# -*- coding:utf-8 -*-
import socket
import time
import threading

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 监听端口:
s.bind(('127.0.0.1', 9999))
s.listen(5)
print('Waiting for connection...')

def tcplink(sock, addr):
print('Accept new connection from %s:%s...' % addr)
sock.send(b'Welcome!')
while True:
data = sock.recv(1024)
time.sleep(1)
if not data or data.decode('utf-8') == 'exit':
break
sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))
sock.close()
print('Connection from %s:%s closed.' % addr)

while True:
# 接受一个新连接:
sock, addr = s.accept()
# 创建新线程来处理TCP连接:
t = threading.Thread(target=tcplink, args=(sock, addr))
t.start()

执行结果

1
2
3
4
5
6
7
8
Waiting for connection...
Accept new connection from 127.0.0.1:52501...
Connection from 127.0.0.1:52501 closed.

Welcome!
Hello, Michael!
Hello, Tracy!
Hello, Sarah!

UDP编程

TCP:是建立可靠连接,并且通信双方都可以以流的形式发送数据。

UDP:是面向无连接的协议,使用 UDP 协议时,不需要建立连接,只需要知道对方的 IP 地址和端口号,就可以直接发数据包。虽然用 UDP 传输数据不可靠,但它的优点是和 TCP 比速度快,对于不要求可靠到达的数据,就可以使用 UDP 协议。

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
#!/usr/bin/python
# -*- coding:utf-8 -*-
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for data in [b'Michael', b'Tracy', b'Sarah']:
# 发送数据:
s.sendto(data, ('127.0.0.1', 9999))
# 接收数据:
print(s.recv(1024).decode('utf-8'))
s.close()


#!/usr/bin/python
# -*- coding:utf-8 -*-
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定端口:
s.bind(('127.0.0.1', 9999))
print('Bind UDP on 9999...')

while True:
# 接收数据:
data, addr = s.recvfrom(1024)
print('Received from %s:%s.' % addr)
s.sendto(b'Hello, %s! ' % data, addr)

执行结果

1
2
3
4
5
6
7
8
Bind UDP on 9999...
Received from 127.0.0.1:58248.
Received from 127.0.0.1:58248.
Received from 127.0.0.1:58248.

Hello, Michael!
Hello, Tracy!
Hello, Sarah!

小结

UDP 的使用与 TCP 类似,但是不需要建立连接。此外,服务器绑定 UDP 端口和 TCP 端口互不冲突,也就是说,UDP9999 端口与 TCP9999 端口可以各自绑定。