学会urllib和requests之后,再来学学底层的TCP协议(UDP鸽了)。
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import sockets = socket.socket() s.connect(('www.baidu.com' , 80 )) s.send(b'GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n' ) buffer = [] while True : d = s.recv(1024 ) if d: buffer.append(d) else : break s.close() data = b'' .join(buffer) header, html = data.split(b'\r\n\r\n' , 1 ) print (header.decode())with open ('t.html' , 'wb' ) as f: f.write(html)
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
,其中AF_INET
指定使用IPv4协议,AF_INET6
表示IPv6。SOCK_STREAM
指定使用面向流的TCP协议。如无特殊情况可以留空。
使用HTTPS:
1 2 3 4 import ssls = ssl.wrap_socket(socket.socket()) s.connect(('www.baidu.com' , 443 ))
服务端
服务端需要打开特定端口监听。一个Socket依赖4项:服务器地址、服务器端口、客户端地址、客户端端口。但是服务器还需要同时相应多个客户端的请求,所以每个连接都需要一个新的进程或线程来处理。
简单的例子,接收客户端连接,把客户端发送的字符串加上Hello
再发回去:
服务端 :
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 import socketimport threadingimport times = socket.socket() s.bind(('127.0.0.1' , 6666 )) s.listen(5 ) print ('Waiting for connection...' )def tcplink (sock, addr ): print ('Accept new connection from %s:%s' % addr) sock.send(b'Welcome!' ) while True : data = sock.recv(1024 ) time.sleep(1 ) if not data or data.decode() == 'exit' : break sock.send((b'Hello, %s!' % data.decode()).encode()) sock.close() print ('Connection for %s:%s closed' % addr) while True : sock, addr = s.accept() t = threading.Thread(target=tcplink, args=(sock, addr)) t.start()
客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 import socketimport randoms = socket.socket() s.connect(('127.0.0.1' , 6666 )) print (s.recv(1024 ).decode())for i in range (5 ): name = chr (random.randint(65 , 90 )) s.send(name.encode()) print (s.recv(1024 ).decode()) s.send(b'exit' ) s.close()
socketserver库
可以创建TCPServer,UDPServer
。方法是定义一个特殊的处理类,继承自BaseRequestHandler
,需要实现一个handle()
方法。可以调用的变量例如self.client_address,self.server,self.request
(对于TCPServer
,可以调用self.request.recv/sendall()
;对于UDPServer
,它是一个tuple(data,socket)
).为实现方便,可以继承自StreamRequestHandler
实例:返回大写的输入内容
UDP
创建UDP服务器