学习爬虫顺便学习一下
网络请求的过程
IP地址和url
动态ip和静态ip的问题
动态ip,对外是不固定的,定时收回更换,同时在家中布置服务器也不现实
静态ip,花钱买呗
url协议
url即资源地址
模板:http://www.example.com:80/path/to/xxx.html?key1=www&key2=333#chap
常用协议:http https file ftp
TCP/IP协议
TCP
是一种面向连接的、可靠的、基于字节流的传输层通信协议。
在协议族中位于IP层之上,应用层之下,负责处理数据流,处理丢包等情况。相当于一个中间者
TCP的三次握手连接(three-way handshake)
ps:SYN(建立连接), ACK(响应) == 数据包 (SYN攻击也是DDoS的一种, 消耗CPU和内存)
流程:Client 向 Server 发送一个 SYN 来创建一个主动打开,Client 把这段连接的序号设为随机数 A ,然后 Server 为合法的 SYN 传回一个 SYN/ACK ,其中 ACK 的确认码为 A+1, SYN/ACK 包序号为随机数 B , 最后 Client 发送 ACK , 序号为 A+1 ,确认码为 B+1 ,Server 收到后就建立连接了,这两发一回就被称为三次握手
TCP的四次握(抛)手断开(four-way handshake)
ps:FIN(关闭连接)
在这个过程中连接的每一侧都独立地被终止。当一个端点要停止它这一侧的连接,就向对侧发送FIN,对侧回复ACK表示确认。因此,拆掉一侧的连接过程需要一对FIN和ACK,分别由两侧端点发出。
首先发出FIN的一侧,如果给对侧的FIN响应了ACK,那么就会超时等待2*MSL时间,然后关闭连接。在这段超时等待时间内,本地的端口不能被新连接使用;避免延时的包的到达与随后的新连接相混淆。RFC793定义了MSL为2分钟,Linux设置成了30s。参数tcp_max_tw_buckets控制并发的TIME_WAIT的数量,默认值是180000,如果超限,那么,系统会把多的TIME_WAIT状态的连接给destory掉,然后在日志里打一个警告(如:time wait bucket table overflow)
Socket
套接字,把复杂的TCP/IP协议藏在接口之后
介绍:socket_client 和 socket_server
socket_server
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| import socket import threading
def handle_sock(sock, addr): tmp_data = sock.recv(1024) print(tmp_data.decode('utf8')) input_data = input() sock.send(input_data.encode('utf8'))
server = socket.socket() server.bind(('0.0.0.0', 8000)) server.listen()
while True: sock, addr = server.accept() client_thread = threading.Thread(target=handle_sock, args=(sock, addr)) client_thread.start()
|
socket_client
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import socket import threading
client = socket.socket() client.connect(('127.0.0.1', 8000)) while True: input_data = input() client.send(input_data.encode('utf8')) server_data = client.recv(1024) print("server response: {}".format(server_data.decode('utf8')))
client.close()
|
应用: qq_client 和 qq_server
qq_server
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
|
import socket from collections import defaultdict import threading import json
online_users = defaultdict(dict)
user_msgs = defaultdict(list) server = socket.socket()
server.bind(('0.0.0.0', 8000)) server.listen()
def handle_sock(sock, addr): while True: data = sock.recv(1024) json_data = json.loads(data.decode('utf8')) action = json_data.get('action', '') if action == "login": online_users[json_data['user']] = sock sock.send("登录成功".encode('utf8')) elif action == "list_user": all_users = [user for user, sock in online_users.items()] sock.send(json.dumps(all_users).encode('utf8')) elif action == 'history_msg': sock.send(json.dumps(user_msgs.get(json_data['user'], [])).encode('utf8')) elif action == 'send_msg': if json_data["to"] in online_users: online_users[json_data["to"]].send(json.dumps(json_data).encode('utf8')) user_msgs[json_data["to"]].append(json_data) elif action == "exit": del online_users[json_data['user']] sock.send("退出成功".encode("utf8"))
while True: sock, addr = server.accept() client_thread = threading.Thread(target=handle_sock, args=(sock, addr)) client_thread.start()
|
qq_client
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| import socket import json import threading
client = socket.socket() client.connect(('192.168.101.15', 8000))
def client_send(msg): client.send(json.dumps(msg).encode("utf8"))
user = "zrzz"
# 1. 登录 login_template = { "action": "login", "user": user, }
client_send(login_template) res = client.recv(1024) print(res.decode('utf8'))
# 2. 获取在线用户 get_user_template = { "action": "list_user" }
client_send(get_user_template) res = client.recv(1024) print("当前在线用户: {}".format(res.decode('utf8')))
# 3.获取历史消息 offline_msg_template = { "action": "history_msg", "user": user }
client_send(offline_msg_template) res = client.recv(1024) print("历史消息: {}".format(res.decode('utf8')))
tuichu = False
def handle_receive(): # 处理接收请求 while True: if not tuichu: try: res = client.recv(1024) except: break res = res.decode("utf8") try: res_json = json.loads(res) if type(res_json) != list: msg = res_json["data"] from_user = res_json["from"] print("受到来自({})的消息: {}".format(from_user, msg)) else: print(res_json) except: print("res") else: break
def handle_send(): while True: # 随时能够收发消息 op_type = input("请输入你要进行的操作: 1. 发送消息, 2. 退出, 3. 获取在线用户\n") if op_type not in ["1", "2", "3"]: print("不支持该操作") elif op_type == "1": to_user = input("请输入你要发送的用户: ") msg = input("请输入你要发送的消息: ") send_data_template = { "action": "send_msg", "to": to_user, "from": user, "data": msg } client_send(send_data_template) elif op_type == "2": exit_template = { "action": "exit", "user": user } client_send(exit_template) client.close() tuichu = True break elif op_type == "3": get_user_template = { "action": "list_user" } client_send(get_user_template)
if __name__ == "__main__": send_thread = threading.Thread(target=handle_send) receive_thread = threading.Thread(target=handle_receive) send_thread.start() receive_thread.start()
|
HTTP协议