学习自Python黑帽子(第二版)
TCP的客户端和服务端
- 前言
- TCP客户端
- TCP服务端
- 问题
- 后记
前言
直接通过实践学习编程,很容易产生一些细节方面的知识错误,遇到不会的俺就问ChatGPT😏
TCP客户端
#快速创建一个TCP客户端对于潜伏在内网环境中没有工具和编译器的时候是一项极其有用的能力import socket
#导入socket模块,它提供了对套接字编程的支持,可以在计算机网络上通信。
#导入后可以实现创建套接字、绑定地址、监听连接请求、发送和接收数据等。target_host = "127.0.0.1"
target_port = 9998client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#socket.AF_INET 是套接字地址簇,表示使用 IPv4 地址族,其中 AF 是 Address Family 的缩写。
#socket.SOCK_STREAM 是套接字类型,表示使用面向连接的 TCP 套接字,其中 SOCK 是 Socket Type 的缩写。
#将这两个参数传递给 socket.socket 函数,将返回一个套接字对象,即 client。
#因此,这条语句的含义是使用 TCP/IP 协议创建一个客户端套接字,以便进行网络通信。client.connect((target_host,target_port))
#connect 是套接字对象的一个方法,用于连接到远程主机。
#如果连接成功,该方法将返回 None。否则,它将引发一个异常,通常是 socket.error 或其子类,指示连接失败的原因。client.send(b"abcd")
# client.send 方法发送一个 HTTP GET 请求(bytes类型)
# GET / HTTP/1.1\r\n:表示使用 HTTP/1.1 协议发送一个 GET 请求,并请求根路径 /。
# Host:baidu.com\r\n:表示请求的主机是 baidu.com。
# \r\n:表示请求头部结束,之后是请求的实体内容。
#字符串前面加上了字母 b,表示将字符串转换为字节串,以便使用 send 方法发送。response = client.recv(4096)print(response.decode())
client.close()
TCP服务端
在这里测试了一下,用上文写的TCP客户端给这里的服务端发送了几个测试的数据包
服务端输出
客户端输出
成功
#编写一个TCP服务端可以被当作远程代码执行工具或者代理工具
import socket
import threadingIP = '0.0.0.0'
PORT = 9998def main():server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)server.bind((IP,PORT))#指定服务器应该监听哪个IP地址和端口server.listen(5)#开始监听print(f'[*] Listening on {IP}:{PORT}')while True:#进入主循环,并等待外来链接client,address = server.accept()#accept() 方法是 Python 中 socket 模块中的一个方法,用于阻塞程序执行,直到有客户端连接请求时才会返回。#返回一个元组包含新的套接字(socket)对象(client)和客户端的地址信息(address)。print(f'[*] Acctepted connection from {address[0]}:{address[1]}')#返回的address也是一个元组,address[0] 表示客户端的 IP 地址,address[1] 表示客户端的端口号#address[0] 和 address[1] 都是字符串类型client_handler = threading.Thread(target=handle_client, args=(client,))#使用 threading 模块来创建和管理线程。创建新的线程时,需要调用 threading.Thread() 构造函数,并指定目标函数和函数参数,即可创建一个新的线程对象。#其中,target 参数是要在新线程中运行的函数,args 参数是传递给目标函数的参数,它应该是一个元组或列表。client_handler.start()#启动新线程def handle_client(client_socket):with client_socket as sock:#with 语句创建一个套接字对象 sock,该套接字对象是 client_socket 参数的别名。#这样,在函数结束时,Python会自动关闭 sock 对象,无需手动调用 close 方法。request = sock.recv(1024)print(f'[*] Received:{request.decode("utf-8")}')#先使用 recv 方法接收客户端发送的数据,最多接收 1024 字节。#然后通过 decode 方法将字节串解码为字符串,并将其打印出来。sock.send(b'ACK')#接着使用 send 方法向客户端发送一个简单的确认消息 b'ACK',表示已经成功接收到客户端的请求。#这里需要注意的是,send 方法只能发送字节串,因此使用 b'ACK' 表示一个字节串。#当 with 语句块执行完毕后,会自动调用 client_socket.close() 方法来关闭套接字连接。这样可以确保在函数结束时正确关闭套接字,避免出现连接泄露等问题。if __name__ == '__main__':#使得导入模块后不会执行之前定义的变量和函数main()
问题
客户端代码中一开始我看服务端监听的是“0.0.0.0”,target_host 的赋值我也就写“0.0.0.0”,但是报错了
OSError: [WinError 10049]
看了看大佬的解答
原因:无法连接到0.0.0.0,因为它不是有效的IP地址。如果将服务器配置为在0.0.0.0上侦听(在每个可用的网络接口上侦听),则应该能够只使用127.0.0.1或localhost。
后记
2023/3/22 | 0:17