python socket
客户端/服务器架构
即C/S架构,包括
1.硬件C/S架构(打印机)
2.软件C/S架构(web服务)
美好的愿望:
最常用的软件服务器是 Web 服务器。一台机器里放一些网页或 Web 应用程序,然后启动 服务。这样的服务器的任务就是接受客户的请求,把网页发给客户(如用户计算机上的浏览器),然 后等待下一个客户请求。这些服务启动后的目标就是“永远运行下去”。虽然它们不可能实现这样的 目标,但只要没有关机或硬件出错等外力干扰,它们就能运行非常长的一段时间。
生活中的C/S架构:
老男孩是S端,所有的学员是C端
饭店是S端,所有的食客是C端
互联网中处处是C/S架构(黄色网站是服务端,你的浏览器是客户端;腾讯作为服务端为你提供视频,你得下个腾讯视频客户端才能看狗日的视频)
C/S架构与socket的关系:
我们学习socket就是为了完成C/S架构的开发
模拟打电话
服务端
import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机 phone.bind(('127.0.0.1',8000)) #绑定手机卡 phone.listen(5) #开机 print("------->") conn,addr = phone.accept() #等电话 msg = conn.recv(1024) #收到消息 print("客户端发来的是",msg) conn.send(msg.upper()) #发消息 conn.close() phone.close()
客户端
import socket phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('127.0.0.1',8000)) #拨通电话 phone.send("hellohgjgjgjk".encode("utf-8")) #发消息 data = phone.recv(1024) print("收到服务端的是:",data) phone.close()
服务端
# tcp服务端 from socket import * ip_port = ("127.0.0.1",8080) back_long = 5 buffer_size = 1024 tcp_sever = socket(AF_INET,SOCK_STREAM) tcp_sever.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #解决重启服务端出现Address already in use tcp_sever.bind(ip_port) tcp_sever.listen(back_long) while True: #外层循环用循环接收不同的链接 print("服务端开始运行了") conn,addr = tcp_sever.accept() print("双向链接是",conn) print("客户端地址是",addr) while True: #内层循环用来基于一次链接循环通信 try: data = conn.recv(buffer_size) if not data:break print('客户端发来的消息是 ',data.decode("utf8")) conn.send(data.upper()) except Exception: break conn.close() tcp_sever.close()
客户端
# tcp客户端 from socket import * ip_port = ("127.0.0.1", 8080) buffer_size = 1024 tcp_client = socket(AF_INET, SOCK_STREAM) tcp_client.connect(ip_port) while True: msg = input(">>>").strip() if not msg:continue tcp_client.send(msg.encode("utf8")) print("客户端已经发消息了") data = tcp_client.recv(buffer_size) print("收到服务端发的消息是 ",data.decode("utf8")) tcp_client.close()
服务端解决粘包
#服务端(自定制报头) from socket import * import subprocess import struct ip_port=('127.0.0.1',8080) back_log=5 buffer_size=1024 tcp_server=socket(AF_INET,SOCK_STREAM) tcp_server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #解决重启服务端出现Address already in use tcp_server.bind(ip_port) tcp_server.listen(back_log) while True: conn,addr=tcp_server.accept() print('新的客户端链接',addr) while True: #收 try: #客户端断开,会捕捉到异常 cmd=conn.recv(buffer_size) if not cmd:break print('收到客户端的命令',cmd) #执行命令,得到命令的运行结果cmd_res res=subprocess.Popen(cmd.decode('utf-8'),shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE, stdin=subprocess.PIPE) err=res.stderr.read() if err: cmd_res=err else: cmd_res=res.stdout.read() #发 if not cmd_res: cmd_res='执行成功'.encode('utf8') length=len(cmd_res) data_length=struct.pack('i',length) conn.send(data_length) conn.send(cmd_res) except Exception as e: print(e) break
客户端解决粘包
#客户端(自定制报头) from socket import * import struct from functools import partial ip_port=('127.0.0.1',8080) buffer_size=1024 tcp_client=socket(AF_INET,SOCK_STREAM) tcp_client.connect(ip_port) while True: cmd=input('>>: ').strip() if not cmd:continue if cmd == 'quit':break tcp_client.send(cmd.encode('utf-8')) #解决粘包 length_data=tcp_client.recv(4) length=struct.unpack('i',length_data)[0] #服务端发回来的数据长度 recv_size=0 recv_msg=b'' while recv_size < length: recv_msg += tcp_client.recv(buffer_size) recv_size=len(recv_msg) #1024 print('命令的执行结果是 ',recv_msg.decode('utf8')) tcp_client.close()
服务端 传文件
from socket import * ip_port = ("127.0.0.1",8182) back_long = 5 buffer_size = 1024 s = socket(AF_INET,SOCK_STREAM) s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) s.bind(ip_port) s.listen(back_long) conn,addr = s.accept() filesize = conn.recv(buffer_size) filesize = int(filesize) p_size = 0 p = b"" while p_size < filesize: p += conn.recv(buffer_size) p_size = len(p) with open("b.jpg","wb") as f: f.write(p) conn.close() s.close()
客户端 传文件
from socket import * import os ip_port = ("127.0.0.1",8182) buffer_size = 1024 c = socket(AF_INET,SOCK_STREAM) c.connect(ip_port) p_size = os.stat("a.jpg").st_size c.send(str(p_size).encode("utf8")) with open("a.jpg","rb") as f: for i in f: # print(i) c.send(i) c.close()
服务端socketserver(解决tcp多用户交流)
import socketserver ip_port = ("127.0.0.1",8081) buffer_size = 1024 class MyServer(socketserver.BaseRequestHandler): def handle(self): print("conn is: ",self.request) #conn print("addr is:",self.client_address) #addr while True: #通信循环 try: data = self.request.recv(buffer_size) if not data:continue print("客户端发来的消息是 ",data.decode("utf8"),self.client_address) self.request.send(data.upper()) except Exception: break if __name__ == "__main__": s = socketserver.ThreadingTCPServer(ip_port,MyServer) s.serve_forever() #链接循环
客户端socketserver(解决tcp多用户交流)
from socket import * ip_port = ("127.0.0.1",8081) buffer_size = 1024 c = socket(AF_INET,SOCK_STREAM) c.connect(ip_port) while True: msg = input(">>>:") c.send(msg.encode("utf8")) data = c.recv(buffer_size) print("服务发来是消息是 ",data.decode()) c.close()
udp服务端
from socket import * ip_port = ("127.0.0.1",8080) buffer_size = 1024 udp_sever = socket(AF_INET,SOCK_DGRAM) udp_sever.bind(ip_port) while True: data,addr = udp_sever.recvfrom(buffer_size) print("客户端发来的是 ",data.decode("utf8")) print("发消息来客户端的地址和端口是 ",addr) udp_sever.sendto(data.upper(),addr)
udp客户端
from socket import * ip_port = ("127.0.0.1",8080) buffer_size = 1024 udp_client = socket(AF_INET,SOCK_DGRAM) while True: msg = input(">>>").strip() udp_client.sendto(msg.encode("utf8"),ip_port) data,addr = udp_client.recvfrom(buffer_size) print("服务端发回的消息是 ",data.decode("utf8"))
udp服务端1
from socket import * import time ip_port = ("127.0.0.1",8080) buffer_size = 1024 udp_sever = socket(AF_INET,SOCK_DGRAM) udp_sever.bind(ip_port) while True: data,addr = udp_sever.recvfrom(buffer_size) if not data: fmt = "%Y-%m-%d %X" else: fmt = data.decode("utf8") back_time = time.strftime(fmt) print(back_time) udp_sever.sendto(back_time.encode("utf8"),addr)
udp客户端1
from socket import * ip_port = ("127.0.0.1",8080) buffer_size = 1024 udp_client = socket(AF_INET,SOCK_DGRAM) while True: msg = input(">>>").strip() udp_client.sendto(msg.encode("utf8"),ip_port) data,addr = udp_client.recvfrom(buffer_size) print("服务端发回的消息是 ",data.decode("utf8"))