第1关:ping服务端创建udp套接字
时间: 2023-05-02 20:04:57 浏览: 227
创建UDP套接字的代码如下:
```python
import socket
udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
```
其中,`socket.AF_INET`表示使用IPv4协议,`socket.SOCK_DGRAM`表示使用UDP协议。创建完成后,就可以使用该套接字进行UDP通信了。
相关问题
第1关:Ping客户端创建原始套接字
好的,首先需要导入socket库来创建原始套接字。然后使用socket库中的socket()函数创建原始套接字,并指定套接字类型为SOCK_RAW。接下来可以使用socket库中的sendto()函数发送Ping请求。代码如下:
```python
import socket
# 构造IP头部
def construct_ip_header(dest_ip):
version = 4 # IPv4
header_length = 5 # 头部长度
tos = 0 # 服务类型
total_length = 84 # 总长度
identification = 54321 # 标识符
flags = 0 # 标志位
fragment_offset = 0 # 片偏移
ttl = 255 # 存活时间
protocol = socket.IPPROTO_ICMP # 协议类型
checksum = 0 # 校验和
source_ip = '192.168.1.100' # 源IP地址
# 把IP头部各字段打包成二进制格式
ip_header = struct.pack('!BBHHHBBH4s4s', (version << 4) + header_length, tos, total_length,
identification, (flags << 13) + fragment_offset, ttl, protocol, checksum,
socket.inet_aton(source_ip), socket.inet_aton(dest_ip))
# 计算IP头部校验和
checksum = calculate_checksum(ip_header)
ip_header = struct.pack('!BBHHHBBH4s4s', (version << 4) + header_length, tos, total_length,
identification, (flags << 13) + fragment_offset, ttl, protocol, checksum,
socket.inet_aton(source_ip), socket.inet_aton(dest_ip))
return ip_header
# 构造ICMP头部
def construct_icmp_header():
type = 8 # 类型为8表示Echo Request
code = 0 # 代码为0
identifier = 1 # 标识符
sequence_number = 1 # 序列号
checksum = 0 # 校验和
# 把ICMP头部各字段打包成二进制格式
icmp_header = struct.pack('!BBHHH', type, code, checksum, identifier, sequence_number)
# 计算ICMP头部校验和
checksum = calculate_checksum(icmp_header)
icmp_header = struct.pack('!BBHHH', type, code, checksum, identifier, sequence_number)
return icmp_header
# 计算校验和
def calculate_checksum(data):
if len(data) % 2 == 1:
data += b'\x00'
res = sum(struct.unpack('!%sH' % (len(data) // 2), data))
res = (res >> 16) + (res & 0xffff)
res += res >> 16
return (~res) & 0xffff
# 发送Ping请求
def ping(dest_ip):
# 创建原始套接字
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
# 构造IP头部和ICMP头部
ip_header = construct_ip_header(dest_ip)
icmp_header = construct_icmp_header()
# 发送Ping请求
s.sendto(ip_header + icmp_header, (dest_ip, 0))
# 接收Ping响应
data, addr = s.recvfrom(1024)
print('Ping response from ', addr)
# 关闭套接字
s.close()
if __name__ == '__main__':
ping('www.baidu.com')
```
需要注意的是,在构造IP头部和ICMP头部时,需要根据协议格式对各字段进行打包,并计算校验和。因为Ping是基于ICMP协议的,所以需要使用IPPROTO_ICMP作为协议类型。
Ping客户端创建原始套接字
可以使用以下代码创建原始套接字:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
int main()
{
int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sockfd < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
char buffer[IP_MAXPACKET];
struct sockaddr_in dest_addr;
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
dest_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
struct icmphdr icmp_header;
memset(&icmp_header, 0, sizeof(icmp_header));
icmp_header.type = ICMP_ECHO;
icmp_header.code = 0;
icmp_header.checksum = htons(~(ICMP_ECHO << 8));
memcpy(buffer, &icmp_header, sizeof(icmp_header));
ssize_t bytes_sent = sendto(sockfd, buffer, sizeof(icmp_header), 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
if (bytes_sent < 0) {
perror("sendto");
exit(EXIT_FAILURE);
}
return 0;
}
```
这个程序创建了一个原始套接字,使用 ICMP 协议发送一个 ICMP_ECHO 请求报文给目标 IP 地址为 127.0.0.1。需要注意的是,需要 root 权限才能运行该程序。