09-Python-Socket编程
一、Python-Socket编程
1.1、弄懂HTTP、Socket、TCP这几个概念
什么是HTTP协议?浏览器的本质就是一个socket客户端遵循HTTP协议,HTTP协议的本质:通过\r\n分割的规范+请求响应之后断开连接。HTTP协议是建立在tcp之上的,HTTP是一种规范,它规定了发送数据的数据格式,这个数据格式是通过\r\n进行分割的,请求头与请求体也是通过2个\r\n分割的。响应的时候,响应头与响应体也是通过\r\n分割,并且规定了请求已响应就会断开连接,是一种短连接,无状态。
什么是socket?socket是应用层与tcp/ip协议族通信的中间软件的抽象层,他是一组接口。在设计模式中,socket其实就是一个门面模式,他把复杂的TCP/IP协议族隐藏在socket接口后面,对用户来说一组接口就是全部。
什么是TCP?TCP三次握手,四次挥手的流程。三次握手:1客户端先向服务器发送SYN状态码,告诉服务器想要建立连接。2然后服务端向客户端回复ACK+SYN状态码告诉客户端可以连接。3然后客户端回复确认ACK状态码给服务器,建立连接。四次挥手:1客户端向服务器发送FIN+SEQ状态码,告诉服务器想要断开。2然后服务器向客户端回复ACK+SEQ状态码,服务器此时进入close-wait状态,等待连接通道数据传输完毕,传输完毕后。3然后服务器向客户端发送FIN+SEQ状态码,此时服务器进入最后确认状态。4最后客户端向服务器发送ACK+SEQ状态码,服务器接收到后立即进入close状态,连接断开。
socket套接字抽象层接口:
1.2、socket和server实现通信
import socket server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#协议 server.bind(('0.0.0.0', 8000)) #地址,端口 server.listen(10) #监听socket客户端请求 sock, addr = server.accept() #阻塞等待连接请求 #获取从客户端发送的数据 #一次获取1k的数据 data = sock.recv(1024) print(data.decode("utf8")) re_data = input() #输入发送给客户端的消息 sock.send(re_data.encode("utf8")) sock.close() #关闭连接 server.close() #关闭服务器
import socket client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect(('127.0.0.1', 8000)) #连接服务端 client.send("lishuntao".encode("utf8")) data = client.recv(1024) print (data.decode("utf8")) client.close()
1.3、socket实现聊天和多用户连接
socket_server:
import socket import threading backlog = 10 server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind(('0.0.0.0', 8000)) server.listen(backlog) def handle_sock(sock, addr): while True: data = sock.recv(1024) if data.decode("utf8") == "Q" or data.decode("utf8") == "q": break print(data.decode("utf8")) re_data = input() sock.send(re_data.encode("utf8")) sock.close() server.close() while True: sock, addr = server.accept() #用线程去处理新接收的连接(用户) client_thread = threading.Thread(target=handle_sock, args=(sock, addr)) client_thread.start()
socket_client:
import socket client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect(('127.0.0.1', 8000)) while True: re_data = input() if re_data.upper() == "Q": break client.send(re_data.encode("utf8")) data = client.recv(1024) print(data.decode("utf8")) client.close()
1.4、socket模拟http请求
#requests(封装了urlib) -> urlib(封装了socket) -> socket(封装TCP/UDP协议) import socket from urllib.parse import urlparse def get_url(url): #通过socket请求html url = urlparse(url) host = url.netloc path = url.path if path == "": path = "/" #建立socket连接 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # client.setblocking(False) client.connect((host, 80)) #阻塞不会消耗cpu #不停的询问连接是否建立好, 需要while循环不停的去检查状态 #做计算任务或者再次发起其他的连接请求 client.send("GET {} HTTP/1.1\r\nHost:{}\r\nConnection:close\r\n\r\n".format(path, host).encode("utf8")) data = b"" while True: d = client.recv(1024) if d: data += d else: break data = data.decode("utf8") html_data = data.split("\r\n\r\n")[1] print(html_data) client.close() if __name__ == "__main__": url = "https://www.baidu.com/" get_url(url)