本文讲解Python网络编程。
C/S架构
C/S(C:client,S:Server)客户机和服务器结构。Server目的就是等待Client的请求,Client连上Server发送必要的数据,然后等待Server端完成请求的反馈。
C/S网络编程 服务器端进行设置,首先创建一个通信端点,让服务器端能够监听请求,之后就进入等待和处理客户机请求的无限循环中。客户机编程相对服务器简单,只要创建一个通信端点,建立到服务器的连接,就可以提出请求了。
套接字
一种具有之前所说的”通信端点“概念的计算机网络数据结构。网络化的应用程序在开始任何通讯之前都必须创建套接字。
Python支持的Socket:AF_UNIX\AF_NETLINK\AF_INET(基于网络的套接字)
Socket模块
socket模块的socket()函数用来创建套接字:socket(socket_family, socket_type, protocol=0)
创建TCP/IP套接字:tcpsock=socket(socket.AF_INET, socket.SOCK_STREAM)
服务器端套接字函数
函数 |
描述 |
s.bind() |
绑定地址(主机,端口)到套接字 |
s.listen() |
开始TCP监听 |
s.accept() |
被动接受TCP客户端连接,等待连接的到来 |
客户端套接字
函数 |
描述 |
s.connect() |
主动初始化TCP服务器连接 |
s.connect_ex() |
Connect函数的扩展版本,出错时返回错误代码,而不是抛出异常 |
公共用途套接字
函数 |
描述 |
s.recv() |
接受TCP数据 |
s.send() |
发送TCP数据 |
s.sendall() |
完整发送TCP数据 |
s.recvfrom() |
接受UDP数据 |
s.sendto() |
发送UDP数据 |
s.getpeemame() |
连接到当前套接字的远端地址 |
s.getsockname() |
当前套接字的地址 |
s.getsockopt() |
返回指定套接字的参数 |
s.setsockopt() |
设置指定套接字的参数 |
s.close() |
关闭套接字(创建使用后记得关闭) |
网络编程示例
创建一个TCP服务器的流程
1 2 3 4 5 6 7 8
| ss = socket.socket() ss.bind(host,port) ss.listen() inf_loop: cs = ss.accept() common_loop: cs.recv()/cs.send() cs.close()
|
创建一个TCP客户端的流程
1 2 3 4 5
| cs.socket() cs.connect() common_loop: cs.recv()/cs.send() cs.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
| from socket import * import time
HOST = '127.0.0.1' PORT = 23342 BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpServer = socket(AF_INET, SOCK_STREAM) tcpServer.bind(ADDR) tcpServer.listen(5)
while True: print('等待连接...') tcpClient, addr = tcpServer.accept() print('连接来自:'+ addr) while True: data = tcpServer.recv(BUFSIZE) if not data: break tcpClient.send('[%s]%s' % (time.ctime(), data))
tcpClient.close() tcpServer.close()
|
1 2
| 等待连接... 连接来自:('127.0.0.1', 54879)
|
编写客户端脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| from socket import * import time
HOST = '127.0.0.1' PORT = 23342 BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpClient = socket(AF_INET, SOCK_STREAM) tcpClient.connect(ADDR)
while True: data = input('~:') if not data: break tcpClient.send(data) data = tcpClient.recv(BUFSIZE) if not data: break print(data)
tcpClient.close()
|
1 2 3 4
| ~:test [Mon Apr 13 20:40:30 2020] test ~:nihao [Mon Apr 13 20:40:40 2020] nihao
|
编写服务器端脚本(shell版本)
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
| from socket import * import time from subprocess import Popen, PIPE
HOST = '127.0.0.1' PORT = 23342 BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpServer = socket(AF_INET, SOCK_STREAM) tcpServer.bind(ADDR) tcpServer.listen(5)
while True: print('等待连接...') tcpClient, addr = tcpServer.accept() print('连接来自:'+ addr) while True: data = tcpServer.recv(BUFSIZE) if not data: break cmd = Popen(['/bin/bash', '-c', data], stdin=PIPE, stdout=PIPE) data = cmd.stdout.read() tcpClient.send('[%s]%s' % (time.ctime(), data))
tcpClient.close() tcpServer.close()
|
1 2
| 等待连接... 连接来自:('127.0.0.1', 54891)
|
重新执行client.py
(在server.py
执行后)
1 2 3
| ~:python3 --version [Mon Apr 13 21:52:41 2020] Python 3.8.1
|