Python全栈开发:socket代码实例
客户端与服务端交互的基本流程
- 服务端server
#!/usr/bin/env python # -*- coding;utf-8 -*- import socket sk = socket.socket() sk.bind(("127.0.0.1", 9999)) sk.listen(5) while True: conn, address = sk.accept() conn.sendall(bytes("欢迎访问老男孩!",encoding="utf-8")) while True: ret_bytes = conn.recv(1024) ret_str = str(ret_bytes, encoding="utf-8") print(ret_str) if ret_str == "q": break conn.sendall(bytes("答:" + "好!", encoding="utf-8"))
- 客户端client
#!/usr/bin/env python # -*- coding;utf-8 -*- import socket obj = socket.socket() obj.connect(("127.0.0.1", 9999)) ret_bytes = obj.recv(1024) ret_str = str(ret_bytes, encoding="utf-8") print(ret_str) while True: inp = input("请输入内容:\n 问:") obj.sendall(bytes(inp, encoding="utf-8")) if inp == 'q': break else: ret = str(obj.recv(1024), encoding="utf-8") print(ret) obj.close()
粘包问题解决方案:一个类型文件发送完毕之后进行一次确认信息交互。
- server(粘包)
#!/usr/bin/env python # -*- coding;utf-8 -*- import socket sk = socket.socket() sk.bind(("192.168.1.107", 9999,)) # 传入元组 sk.listen(5) # 监听客户端请求,最多有五个客户端请求等待) # 连接,客户端的地址信息(IP,port) while True: conn, address = sk.accept() # accept表示阻塞,等待连接请求 conn.sendall(bytes("欢迎访问老男孩!", encoding="utf-8")) file_size = str(conn.recv(1024), encoding="utf-8") print(file_size) conn.sendall(bytes("开始吧!", encoding="utf-8")) total_size = int(file_size) has_recv = 0 with open("c11.py", "wb") as f: i = 0 while True: if total_size == has_recv: print("接收完毕!") break data = conn.recv(1024) f.write(data) has_recv += len(data) obj.close()
- client(粘包)
#!/usr/bin/env python # -*- coding;utf-8 -*- import socket import os obj = socket.socket() obj.connect(("192.168.1.107", 9999)) result_bytes = obj.recv(1024) # 等待发送消息 result_str = str(result_bytes, encoding="utf-8") print(result_str) # 发送当前文件大小 file_size = os.stat("client(粘包).py").st_size print("文件大小:" + str(file_size)) obj.sendall(bytes(str(file_size), encoding="utf-8")) obj.recv(1024) with open("client(粘包).py", "rb") as f: seed_size = 0 for i, line in enumerate(f, 1): obj.sendall(line) seed_size += len(line) if seed_size == file_size: print("发送完毕!") obj.close()
IO多路复用在socket中的运用:针对老用户和新用户,服务器做出不同的响应
- server服务端
#!/usr/bin/env python # -*- coding;utf-8 -*- """ IO多路复用socket实例代码 """ import socket import select sk1 = socket.socket() sk1.bind(("127.0.0.1", 8001)) sk1.listen(5) inputs = [sk1, ] info_sender = [] message = {} while True: # select自动监听文件描述符,发生变化则放入r_list列表中 r_list, w_list, e_list = select.select(inputs, info_sender, [], 1) # print("正在监听的对象数量:%d" % len(inputs)) for sk in r_list: # sk 表示每个连接对象 if sk == sk1: # 有新用户建立连接 conn, address = sk.accept() conn.sendall(bytes("hello", encoding="utf-8")) inputs.append(conn) message[conn] = [] else: # 有老用户发送信息 try: date = str(sk.recv(1024), encoding="utf-8") except Exception as e: e_list.append(sk) else: if sk not in info_sender: info_sender.append(sk) message[sk].append(date) for sk in w_list: re = message[sk][0] del message[sk][0] sk.sendall(bytes(re + "hello", encoding="utf-8")) # 给我发送信息的对象,我回复了信息就要把它排除,不然前面有while循环,和for循环,就会不断给对方回复消息! info_sender.remove(sk) for sk in e_list: inputs.remove(sk)
- 客户端client(client1,client2,client3):当用户第一次连接时执行相同的操作,支持多用户与服务器交互,客户端断开连接,服务器不受影响
#!/usr/bin/env python # -*- coding;utf-8 -*- import socket sk1 = socket.socket() sk1.connect(("127.0.0.1", 8001)) while True: content1 = str(sk1.recv(1024), encoding="utf-8") a = [] print(content1) while True: inp = input(">>>") if inp == "q": a.append(inp) break else: sk1.sendall(bytes(inp, encoding="utf-8")) content2 = str(sk1.recv(1024), encoding="utf-8") print(content2) if a == ["q"]: break sk1.close()