【发布时间】:2014-11-23 03:39:44
【问题描述】:
我正在使用原始套接字发送数据报,如this 教程(第 III 节)中所述。但是,我无法正确打印响应(显示垃圾字符)。不知道程序有什么问题。 任何人都能够识别错误?
#define P 80 /* TCP port 80 - HTTP */
unsigned short /* this function generates header checksums */
csum(unsigned short *buf, int nwords)
{
//checksum code here, omitting for stackoverflow question
}
int main()
{
int s = socket(PF_INET, SOCK_RAW, IPPROTO_TCP); /* open raw socket */
char datagram[4096]; /* this buffer will contain ip header, tcp header,
and payload. we'll point an ip header structure
at its beginning, and a tcp header structure after
that to write the header values into it */
struct ip *iph = (struct ip *) datagram;
struct tcphdr *tcph = (struct tcphdr *) datagram + sizeof(struct ip);
struct sockaddr_in sin;
/* the sockaddr_in containing the dest. address is used
in sendto() to determine the datagrams path */
sin.sin_family = AF_INET;
sin.sin_port = htons(P);/* you byte-order >1byte header values to network
byte order (not needed on big endian machines) */
sin.sin_addr.s_addr = inet_addr("74.125.224.72"); //google's ip address
memset(datagram, 0, 4096); /* zero out the buffer */
/* we'll now fill in the ip/tcp header values, see above for explanations */
iph->ip_hl = 5;
iph->ip_v = 4;
iph->ip_tos = 0;
iph->ip_len = sizeof(struct ip) + sizeof(struct tcphdr); /* no payload */
iph->ip_id = htonl(54321); /* the value doesn't matter here */
iph->ip_off = 0;
iph->ip_ttl = 255;
iph->ip_p = 6;
iph->ip_sum = 0; /* set it to 0 before computing the actual checksum later */
iph->ip_src.s_addr = inet_addr("1.2.3.4");/* SYN's can be blindly spoofed */
iph->ip_dst.s_addr = sin.sin_addr.s_addr;
tcph->th_sport = htons(1234); /* arbitrary port */
tcph->th_dport = htons(P);
tcph->th_seq = random();/* in a SYN packet, the sequence is a random */
tcph->th_ack = 0;/* number, and the ack sequence is 0 in the 1st packet */
tcph->th_x2 = 0;
tcph->th_off = 0; /* first and only tcp segment */
tcph->th_flags = TH_SYN; /* initial connection request */
tcph->th_win = htonl(65535); /* maximum allowed window size */
tcph->th_sum = 0;/* if you set a checksum to zero, your kernel's IP stack
should fill in the correct checksum during transmission */
tcph->th_urp = 0;
iph->ip_sum = csum((unsigned short *) datagram, iph->ip_len >> 1);
/* finally, it is very advisable to do a IP_HDRINCL call, to make sure
that the kernel knows the header is included in the data, and doesn't
insert its own header into the packet before our data */
int one = 1;
const int *val = &one;
if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
printf("Warning: Cannot set HDRINCL!\n");
if (sendto(s,datagram,iph->ip_len,0,(struct sockaddr *) &sin, sizeof(sin)) < 0)
printf("error\n");
else
printf(".\n\n");
sleep(2); // giving enough time to receive response
char buffer[8192]; /* single packets are usually not bigger than 8192 bytes */
memset(buffer, 0, 8192); /* zero out the buffer */
while (recv(s, buffer, 8192, 0) > 0)
printf("Caught tcp packet: %s\n", buffer + sizeof(struct iphdr) + sizeof(struct tcphdr));
close(s);
return 0;
}
我得到的输出如下图所示:http://imgur.com/jjjhp39
【问题讨论】:
-
首先,使用Wireshark等工具查看网络上发生了什么。其次,您似乎正在尝试establish a connection,在这种情况下,您将不会收到任何数据的回复。而且你甚至不检查如果你得到回复数据,你只是打印“数据”。
-
我认为程序只有在使用
recv()函数接收到一些数据时才会打印。既然是SYN包,我认为服务器应该发送一个ACK。 -
由于您使用的是原始套接字,因此您收到的数据包将包含 IP 和 TCP 标头,这些将计入返回的大小中。
-
你的意思是:服务器的响应中不会有任何有效负载?
-
如果您发送一个
SYN数据包,您应该会收到一个ACK+SYN(或RST)回复,并且该数据包不会有任何负载。
标签: c++ c sockets network-programming raw-sockets