Python 中的 socket
是一个用于网络通信的基本模块,我们可以使用 socket
来进行简单的网络通信以及深入了解 socket
。
socket 对象
首先我们来了解一下 socket
对象。
socket 的建立
这一部分我们会使用简单的示例来演示 socket
的建立。
- 客户端的
socket
可以由以下几种方式创建:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 创建一个 socket 对象,AF_INET 指定使用 IPV4 地址,SOCK_STREAM 指定使用 TCP 协议
s.connect(('www.baidu.com', 80))
# 连接到 www.baidu.com 地址的 80 端口
# do something
或者
import socket
with socket.create_connection(('www.baidu.com', 80)) as s:
# do something
- 服务端的
socket
可以由以下几种方式创建:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 9999))
# 绑定端口
s.listen(5)
# 监听端口,最多可以接受 5 个连接
while True:
# 接受一个新连接
c, addr = s.accept()
# 创建新的 socket 对象
# do something
或者
import socket
with socket.create_server(('localhost', 9999)) as s:
c, addr = s.accept()
# do something
如果想同时支持 IPv6,也可以
import socket
kwargs = {'family': socket.AF_INET6, 'dualstack_ipv6': True} if socket.has_dualstack_ipv6() else {}
with socket.create_server(('localhost', 9999), **kwargs) as s:
c, addr = s.accept()
# do something
数据的发送和接收
- 发送数据
s.send(b'Hello, world')
# 发送 TCP 数据,发送的数据必须是 `bytes` 类型,如果是字符串,需要先进行编码。
# 该方法不保证能够发送所有的数据,返回值为实际发送的字节数。
s.sendall(b'Hello, world')
# 类似于 `send`,但是如果发送不完,则会一直等待直到发送完毕。
# 发送成功后返回 `None`,如果发送失败,则抛出异常。
s.sendfile(file)
# 发送文件。
# 发送成功后返回发送字节总数。
- 接收数据
data = s.recv(1024)
# 接收 TCP 数据,接收的数据是 `bytes` 类型,如果收到的数据实为字符串,需要先进行解码。
# 该方法需要指定接收的最大字节数,返回值为实际接收到的数据。
关闭连接
s.close()
# 关闭连接
s.shutdown(socket.SHUT_RDWR)
# 关闭连接,同时关闭发送和接收。
提高性能
上面的示例中,我们的实现是单线程的,如果要提高性能,可以使用多线程或者多进程。
import socket
import threading
def handle_request(sock, addr):
print('Accept new connection from %s:%s...' % addr)
# do something
sock.close()
print('Connection from %s:%s closed.' % addr)
with socket.create_server(('localhost', 9999)) as s:
while True:
c, addr = s.accept()
t = threading.Thread(target=handle_request, args=(c, addr))
t.start()
或者
import socket
import multiprocessing
def handle_request(sock, addr):
print('Accept new connection from %s:%s...' % addr)
# do something
sock.close()
print('Connection from %s:%s closed.' % addr)
with socket.create_server(('localhost', 9999)) as s:
while True:
c, addr = s.accept()
t = multiprocessing.Process(target=handle_request, args=(c, addr))
t.start()
一个简单的登录认证服务器
我们来看一个简单的登录认证服务器,它可以接收密钥,并返回一个登录结果。
- 服务端
import socket
import multiprocessing
import hashlib
token = input('Please input the token: ').strip()
hashed_token = hashlib.sha256(token.encode('utf-8')).hexdigest()
def handle_request(sock, addr):
print('Accept new connection from %s:%s...' % addr)
cli_hash = sock.recv(1024).decode('utf-8')
if hashed_token == cli_hash:
sock.send(b'OK')
else:
sock.send(b'Bad token')
sock.close()
print('Connection from %s:%s closed.' % addr)
with socket.create_server(('localhost', 9999)) as s:
while True:
c, addr = s.accept()
t = multiprocessing.Process(target=handle_request, args=(c, addr))
t.start()
- 客户端
import socket
import hashlib
token = input('Please input the token: ').strip()
hashed_token = hashlib.sha256(token.encode('utf-8')).hexdigest()
with socket.create_connection(('localhost', 9999)) as s:
s.send(hashed_token.encode('utf-8'))
ret = s.recv(1024).decode('utf-8')
print(ret)
文章评论