Python 提供了两个级别访问的网络服务:
- 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统 Socket 接口的全部方法。
- 高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。
什么是 Socket?
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
简单实例
服务端
我们使用 socket 模块的 socket 函数来创建一个 socket 对象。socket 对象可以通过调用其他函数来设置一个 socket 服务。
现在我们可以通过调用 bind(hostname, port) 函数来指定服务的 port(8080)。
接着,我们调用 socket 对象的 accept 方法。该方法等待客户端的连接,并返回 connection 对象,表示已连接到客户端。
1 #服务端代码 2 import socket 3 import subprocess 4 import struct 5 import json 6 7 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 8 phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 重复使用端口 9 phone.bind((‘127.0.0.1‘, 8080)) 10 phone.listen(5) 11 print(‘start...‘) 12 while True: 13 coon, client_add = phone.accept() 14 print(client_add) 15 while True: 16 try: 17 cmd = coon.recv(1024) 18 if not cmd: 19 break 20 obj = subprocess.Popen( 21 cmd.decode(‘utf-8‘), 22 shell=True, 23 stdout=subprocess.PIPE, 24 stderr=subprocess.PIPE) 25 stdout = obj.stdout.read() 26 stderr = obj.stderr.read() 27 # 1.制作固定长度报头 28 header_dic = { 29 ‘filename‘: ‘a.txt‘, 30 ‘md5‘: ‘soigiojalks‘, 31 ‘total_size‘: len(stdout) + len(stderr) 32 } 33 header_json = json.dumps(header_dic) 34 header_bytes = header_json.encode(‘utf-8‘) 35 # 发送报头长度 36 coon.send(struct.pack(‘i‘, len(header_bytes))) 37 # 2.把报头发送给客户端 38 coon.send(header_bytes) 39 # 3.发送真实数据 40 coon.send(stdout) 41 coon.send(stderr) 42 except ConnectionResetError: 43 break 44 coon.close() 45 phone.close()
客户端
接下来我们写一个简单的客户端实例连接到以上创建的服务。端口号为 8080。
socket.connect(hosname, port ) 方法打开一个 TCP 连接到主机为 hostname 端口为 port 的服务商。连接后我们就可以从服务端获取数据,记住,操作完成后需要关闭连接。
完整代码如下:
1 # 客户端 2 import json 3 import socket 4 import struct 5 6 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 7 phone.connect((‘127.0.0.1‘, 8080)) 8 while True: 9 cmd = input(‘>>‘).strip() 10 if not cmd: 11 continue 12 phone.send(cmd.encode(‘utf-8‘)) 13 # 1.接收报头 14 header = phone.recv(4) 15 # 2.从报头中解析真实数据描述信息(报头长度) 16 header_size = struct.unpack(‘i‘, header)[0] 17 header_bytes = phone.recv(header_size) 18 header_json = header_bytes.decode(‘utf-8‘) 19 header_dic = json.loads(header_json) 20 print(header_dic) 21 total_size = header_dic[‘total_size‘] 22 recv_size = 0 23 recv_data = b‘‘ 24 while recv_size < total_size: 25 res = phone.recv(1024) 26 recv_data += res 27 recv_size += len(res) 28 print(recv_data.decode(‘utf-8‘)) 29 phone.close()
此代码已解决粘包问题!!!
网络编程常见面试题:
1.python中,网络编程有哪些常用模块?
2.socket对象内建方法有哪些?
3.HTTP是什么?它与HTTPS有什么区别?
4.说说HTTP请求报文与响应报文格式。
5.TCP为什么会粘包?