data, addr = sock_udp.recvfrom(1024) print '[UDP] Total Data len recv ' + str(len(data)) id = struct.unpack('>H', data[0:2])[0] query = data[12:] data = dw(id) # id data += dw(0x85a0) # flags data += dw(1) # questions data += dw(0x52) # answers data += dw(0) # authoritative data += dw(0) # additional # Add the question back - we're just hardcoding it data += ('\x03125\x018\x018\x018\x07in-addr\x04arpa\x00' + '\x00\x0c' + # type = 'PTR' '\x00\x01') # cls = 'IN' # Add the first answer data += ('\xc0\x0c' + # ptr to the name '\x00\x0c' + # type = 'PTR' '\x00\x01' + # cls = 'IN' '\x00\x00\x00\x3d' + # ttl '\x04\x00' + # size of this resource record '\x3e' + 'Z'*62 + '\x3e' + 'Z'*62 + '\x3e' + 'Z'*62 + '\x3e' + 'Z'*62 + '\x3e' + 'Z'*62 + '\x3e' + 'Z'*62 + '\x3e' + 'Z'*62 + '\x3e' + 'Z'*62 + '\x3e' + 'Z'*62 + '\x3e' + 'Z'*62 + '\x3e' + 'Z'*62 + '\x3e' + 'Z'*62 + '\x3e' + 'Z'*62 + '\x3e' + 'Z'*62 + '\x3e' + 'Z'*62 + '\x3e' + 'Z'*62 + '\x0e' + 'Z'*14 + '\x00') # Add the next answer, which is written out in full data += ('\xc0\x0c' + # ptr to the name '\x00\x0c' + # type = 'PTR' '\x00\x01' + # cls = 'IN' '\x00\x00\x00\x3d' + # ttl '\x00\x26' + # size of this resource record '\x08DCBBEEEE\x04DDDD\x08CCCCCCCC\x04AAAA\x04BBBB\x03com\x00')
时间: 2024-04-27 08:24:11 浏览: 83
这段代码实现了一个 DNS 服务器的响应报文的构造过程。首先,使用 UDP 协议接收来自客户端的 DNS 查询报文(不超过 1024 字节),其中包含了查询的 domain 名称,然后解析出查询的 id 和问题部分的数据。接着,根据 DNS 协议的规定,构造 DNS 响应报文,并将其打包成二进制数据。具体来说,响应报文的格式如下:
1. 16 位的 id,与查询报文的 id 相同。
2. 16 位的 flags,表示响应报文的状态信息。
3. 16 位的 questions,表示查询的问题数,这里为 1。
4. 16 位的 answers,表示响应的回答数,这里为 1。
5. 16 位的 authoritative,表示授权回答数,这里为 0。
6. 16 位的 additional,表示附加回答数,这里为 0。
接着,构造响应报文中的 question 部分,这里是一个固定的反向 DNS 查询报文,即查询 IP 地址对应的域名。然后,构造响应报文中的 answer 部分,包含了两个 PTR 类型的回答记录,分别是查询 IP 地址对应的两个域名的反向映射结果。其中,第一个 PTR 记录的数据部分由 16 个 62 字节的字符串和一个 14 字节的字符串组成,第二个 PTR 记录的数据部分是一个完整的 PTR 记录,它将查询 IP 地址映射到一个域名。最后,将构造好的 DNS 响应报文通过 UDP 协议发送给客户端。
相关问题
import socket # 客户端的IP地址和端口号 client_ip = '192.168.1.1'client_port = 12345 # 服务器的IP地址和端口号 server_ip = '202.112.20.132'server_port = 54321 # 创建UDP套接字 client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 绑定客户端的IP地址和端口号 client_socket.bind((client_ip, client_port)) # 发送数据 data = 'Hello, this is client.'client_socket.sendto(data.encode(), (server_ip, server_port)) # 接收数据 recv_data, addr = client_socket.recvfrom(1024)print('Received data: ', recv_data.decode()) # 关闭套接字 client_socket.close()将以上程序变为C语言的socket程序
以下是将Python程序转化为C语言程序的过程:
```
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#define CLIENT_IP "192.168.1.1"
#define CLIENT_PORT 12345
#define SERVER_IP "202.112.20.132"
#define SERVER_PORT 54321
int main() {
int client_socket;
char buffer[1024];
struct sockaddr_in client_addr, server_addr;
socklen_t server_addr_len;
// 创建客户端套接字
client_socket = socket(AF_INET, SOCK_DGRAM, 0);
if(client_socket < 0) {
perror("socket");
exit(1);
}
// 绑定客户端IP地址和端口号
bzero(&client_addr, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = inet_addr(CLIENT_IP);
client_addr.sin_port = htons(CLIENT_PORT);
if(bind(client_socket, (struct sockaddr*)&client_addr, sizeof(client_addr)) < 0) {
perror("bind");
exit(1);
}
// 设置服务器IP地址和端口号
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
server_addr.sin_port = htons(SERVER_PORT);
server_addr_len = sizeof(server_addr);
// 发送数据
strcpy(buffer, "Hello, this is client.");
if(sendto(client_socket, buffer, strlen(buffer), 0, (struct sockaddr*)&server_addr, server_addr_len) < 0) {
perror("sendto");
exit(1);
}
// 接收数据
bzero(buffer, sizeof(buffer));
if(recvfrom(client_socket, buffer, sizeof(buffer), 0, (struct sockaddr*)&server_addr, &server_addr_len) < 0) {
perror("recvfrom");
exit(1);
}
printf("Received data: %s\n", buffer);
// 关闭套接字
close(client_socket);
return 0;
}
```
转化后的C语言程序与原来的Python程序实现的功能相同,都是通过UDP协议向服务器发送"Hello, this is client."字符串,并从服务器接收数据。
优化并改编以下代码,使其和原来有部分出入但实现效果相同: 1. import socket 2. 3. 4. def receive(): 5. # 创建套接字 6. udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 7. 8. # 准备数据9. file_name = input("Please input the save file name:") 10. 11. # 发送数据 12. ip = input("Please input the sender's ipv4 address:") 13. udp_socket.sendto(file_name.encode('gbk'), (ip, 7788)) 14. 15. # 接收数据 16. recv_data = udp_socket.recvfrom(1024) 17. file_data = recv_data[0] 18. with open(file_name, 'wb') as f: 19. f.write(file_data) 20. print("Receive successfully!") 21. # 关闭套接字 22. udp_socket.close() 23. 24. 25.def send(): 26. # 创建套接字 27. udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 28. 29. # 绑定本地信息 30. localaddr = ('', 7788) 31. udp_socket.bind(localaddr) 32. 33. # 接收数据 34. while True: 35. recv_data = udp_socket.recvfrom(1024) 36. recv_msg = recv_data[0] 37. send_addr = recv_data[1] 38. print("%s:%s" % (str(send_addr), recv_msg.decode('gbk'))) 39. 40. # 读取文件并传输文件 41. with open(recv_msg.decode('gbk'), 'rb') as f: 42. file_data = f.read() 43. udp_socket.sendto(file_data, send_addr) 44. 45. print("Send successfully!") 46. break 47. 48. # 关闭套接字 49. udp_socket.close() 50. 51. 52.if name == 'main': 3553. while True: 54. answer = input("This is a simple program relying on the Udp protocol, \nif you want to send the file," 55. "please input 1,\n if you want to receive th e file, please input 2, \n if you want exit, " 56. "please input 0:\n") 57. if answer == '0': 58. break 59. if answer == '1': 60. send() 61. if answer == '2': 62. receive()
以下是优化并改编后的代码,改动主要是将 receive() 和 send() 函数中的 input() 改为函数参数接收:
```
import socket
def receive(file_name, ip):
# 创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 发送数据
udp_socket.sendto(file_name.encode('gbk'), (ip, 7788))
# 接收数据
recv_data = udp_socket.recvfrom(1024)
file_data = recv_data[0]
with open(file_name, 'wb') as f:
f.write(file_data)
print("Receive successfully!")
# 关闭套接字
udp_socket.close()
def send(file_path):
# 创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定本地信息
localaddr = ('', 7788)
udp_socket.bind(localaddr)
# 接收数据
while True:
recv_data = udp_socket.recvfrom(1024)
recv_msg = recv_data[0]
send_addr = recv_data[1]
print("%s:%s" % (str(send_addr), recv_msg.decode('gbk')))
# 读取文件并传输文件
with open(file_path, 'rb') as f:
file_data = f.read()
udp_socket.sendto(file_data, send_addr)
print("Send successfully!")
break
# 关闭套接字
udp_socket.close()
if __name__ == '__main__':
while True:
answer = input("This is a simple program relying on the Udp protocol, \nif you want to send the file, please input 1,\nif you want to receive the file, please input 2, \nif you want exit, please input 0:\n")
if answer == '0':
break
if answer == '1':
file_path = input("Please input the file path to send:")
send(file_path)
if answer == '2':
file_name = input("Please input the save file name:")
ip = input("Please input the sender's ipv4 address:")
receive(file_name, ip)
```
改编后的代码中,receive() 和 send() 函数分别接收一个参数,即文件名或文件路径,而不是通过 input() 函数从命令行读取。这样可以使代码更加模块化和可重用。同时,代码中的注释也进行了修改和补充,以提高代码可读性和易懂性。
阅读全文