一、客户端/服务器架构
客户端:因特定需求联系服务器,并发送必要的数据,然后等待服务器响应,最后完成请求或给出故障原因。对服务进行一次性请求。
服务器:一组硬件和软件,为一个或多个客户端服务。存在的唯一目的就是等待客户端请求,并响应然后等待更多请求。服务器无限运行,并不断处理请求
- 硬件客户端/服务器架构,例:打印机服务器、文件服务器
- 软件客户端/服务器架构,例:Web服务器、数据库服务器、窗体服务器
二、套接字(socket):通信端点,监听请求
套接字地址:(主机名,端口号)
UDP:成本低廉,不需大量的维护,例如:使用面向连接的协议
1、socket模块函数
创建套接字
1 import socket 2 tco_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 3 udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
缩短代码:
1 from socket import * #将socket模块引入命名空间 2 tco_socket = socket(AF_INET, SOCK_STREAM) 3 udp_socket = socket(AF_INET, SOCK_DGRAM)
1.1、套接字的内置方法:
1.2、创建TCP服务器/客户端
1.2.1、创建TCP服务器
1 ''' 2 创建TCP服务器,创建TCP服务器,接受客户端发送的字符串,并将其打上时间戳并返回给客户端 3 ''' 4 from socket import * 5 from time import ctime 6 7 HOST = '' #主机名 8 PORT = 21567 #端口号 9 BUF_SIZE = 1024 #缓冲区大小 10 ADDR = (HOST, PORT) 11 12 tcp_sersock = socket(AF_INET, SOCK_STREAM) 13 tcp_sersock.bind(ADDR) #套接字绑定服务器地址 14 tcp_sersock.listen(5) #传入连接请求的最大数 15 try: 16 while True: 17 print('Waiting for connection...') 18 tcp_clisock, addr = tcp_sersock.accept() #接受客户端连接,返回客户端套接字,空出原始服务器套接字,使其可等待其它客户端请求 19 print('...connected from:', addr) 20 21 while True: 22 data = tcp_clisock.recv(BUF_SIZE).decode() #客户端套接字接受TCP消息,当一方关闭连接或向对方发送一个空字符串,连接关闭 23 if not data: 24 break 25 tcp_clisock.send(('[%s] %s ' % (ctime(), data)).encode()) 26 tcp_clisock.close() #关闭临时客户端套接字 27 except ValueError: #传入一个调用者不期望的值,即使值的类型是正确的 28 tcp_sersock.close() #关闭服务端套接字,但一般服务器应无限循环运行,若服务器要实现智能退出方案,建议使用close()
注:
- 若支持IPv6,创建套接字时为AF_INET6
- 优雅地退出和调用服务器close()方法,使用try-except方法
1.2.2、创建TCP客户端
''' 创建TCP客户端, 连接到服务器,并以逐行数据的形式提示用户,服务器则返回加入时间戳的相同诗句,并通过客户端展示给用户 ''' from socket import * HOST = 'localhost' #服务器主机名 or'127.0.0.1 ' PORT = 21567 #服务器端口号 BUF_SIZE = 1024 #缓冲区大小 ADDR = (HOST, PORT) tcp_clisock = socket(AF_INET, SOCK_STREAM) tcp_clisock.connect(ADDR) #创建到服务器的连接 while True: data = input('>') if not data: break tcp_clisock.send(data.encode()) data = tcp_clisock.recv(BUF_SIZE).decode() if not data: break print(data) tcp_clisock.close()
注:注意编码方式的转换
1.2.3、 执行TCP服务器和客户端
先执行服务器再执行客户端,若修改主机名则服务器在其他电脑上运行
>>>服务器端:
Waiting for connection... ...connected from: ('127.0.0.1', 45529)
>>>客户端:
>lll
[Sun Mar 4 16:27:47 2018] lll
1.3、创建UDP服务器和客户端
1.3.1、创建UDP服务器
1 ''' 2 创建UDP服务器,接受客户端发来的消息,并加入时间戳前缀的该消息返回给客户端 3 ''' 4 5 from socket import * 6 from time import ctime 7 8 HOST = '' 9 PORT = 21567 10 BUF_SIZE = 1024 11 ADDR = (HOST, PORT) 12 13 udp_sersock = socket(AF_INET, SOCK_DGRAM) 14 udp_sersock.bind(ADDR) 15 try: 16 while True: 17 print('Waiting for message...') 18 data, addr = udp_sersock.recvfrom(BUF_SIZE) 19 20 udp_sersock.sendto(('[%s] %s ' % (ctime(), data.decode())).encode(), addr) 21 print('...received from and returned to:', addr) 22 except ValueError: 23 udp_sersock.close()
1.3.2创建UDP客户端
1 ''' 2 创建UDP客户端,提示用户输入发送到服务器的消息,并接受服务器加入时间戳的消息,然后显示给用户 3 ''' 4 5 from socket import * 6 7 HOST = 'localhost' 8 PORT = 21567 9 BUF_SIZE = 2014 10 ADDR = (HOST, PORT) 11 12 upd_clisock = socket(AF_INET, SOCK_DGRAM) 13 14 while True: 15 data = input('>') 16 if not data: 17 break 18 upd_clisock.sendto(data.encode(), ADDR) 19 data, ADDR = upd_clisock.recvfrom(BUF_SIZE) 20 if not data: 21 break 22 print(data.decode()) 23 upd_clisock.close()