Zhang Yue's explanation of Visual C ++ network programming examples is very good, and his code is very beautiful!
Books on network programming were abandoned for a long time. Pick up again in this period of time to fill in the deficiencies!
This is an example of his first chapter. Simulate ping to send ICMP Packets:
1. program source code
//////////////////////////////////////// //// // <Br/> // comm. hfile </P> <p> // contains some common functions </P> <p> # ifndef _ comm_h __< BR/> # DEFINE _ comm_h __</ p> <p> // calculate the checksum <br/> // Add the buffer content in 16-bit characters, if the buffer length is an odd number, <br/> // Add a byte. <Br/> ushortchecksum (ushort * buff, int size); </P> <p> boolsetttl (socket s, int nvalue); <br/> boolsettimeout (socket S, int ntime, bool brecv = true); </P> <p> # endif/_ comm_h __
//////////////////////////////////////// //// // <Br/> // protoinfo. hfile </P> <p>/* </P> <p> define the Protocol format <br/> define the macros used in the Protocol </P> <p> */ </P> <p> # ifndef _ protoinfo_h __< BR/> # DEFINE _ protoinfo_h __</P> <p> # define ethertype_ip 0x0800 <br/> # define ethertype_arp 0x0806 </P> <p> typedef struct _ etheader // 14-byte Ethernet header <br/>{< br/> uchardhost [6]; // destination MAC address <br/> ucharshost [6]; // source MAC address <br/> Ushorttype; // underlying protocol type, such as IP (ethertype_ip) and ARP (ethertype_arp) <br/>} etheader, * petheader; </P> <p> # define arphrd_ether 1 </P> <p> // ARP Opcodes <br/> # definearpop_request1 // ARP request <br/> # definearpop_reply2/ /ARP response </P> <p> typedef struct _ arpheader // 28-byte ARP header <br/>{< br/> ushorthrd; // hardware address space, which is arphrd_ether over Ethernet. <br/> ushorteth_type; // Ethernet type, ethertype_ip ?? <Br/> ucharmaclen; // length of the MAC address, which is 6 <br/> uchariplen; // length of the IP address, which is 4 <br/> ushortopcode; // operation code, arpop_request is a request, and arpop_reply is a response <br/> ucharsmac [6]; // source MAC address <br/> ucharsaddr [4]; // source IP address <br/> uchardmac [6]; // destination MAC address <br/> uchardaddr [4]; // destination IP address <br/>} arpheader, * parpheader; </P> <p> // protocol <br/> # define proto_icmp 1 <br/> # define proto_igmp 2 <br/> # define proto_tcp 6 <br/> # define proto_udp 17 </P> <p> typedef struct _ ipheader // 20-byte IP header <br/>{< br/> uchar iphverlen; // version number and header length (4 digits each) <br/> uchar iptos; // service type <br/> ushort iplength; // total package length, that is, the length of the IP packet <br/> ushort ipid; // The packet ID, which uniquely identifies each datagram sent <br/> ushort ipflags; // flag <br/> uchar ipttl; // TTL <br/> uchar ipprotocol; // protocol, it may be TCP, UDP, ICMP, etc. <br/> ushort ipchecksum; // checksum <br/> ulong ipsource; // source IP address <br/> ulong ipdestination; // target IP address <br/>} ipheader, * pipheader; </P> <p> // define the TCP flag <br/> # define tcp_fin 0x01 <br/> # define tcp_syn 0x02 <br/> # define tcp_rst 0x04 <br/> # define tcp_psh 0x08 <br/> # define tcp_ack 0x10 <br/> # define tcp_urg 0x20 <br/> # define tcp_ace 0x40 <br/> # define tcp_cwr 0x80 </P> <p> typedef struct _ tcpheader // 20-byte TCP Header <br/> {<br/> ushortsourceport; // 16-bit source port number <br/> ushortdestinationport; // 16-bit destination port number <br/> ulongsequencenumber; // 32-bit serial number <br/> ulongacknowledgenumber; // 32-bit confirmation number <br/> uchardataoffset; // 4-bit height indicates data offset <br/> ucharflags; // 6-digit flag <br/> // fin-0x01 <br/> // syn-0x02 <br/> // RST-0x04 <br/> // push-0x08 <br/> // ack-0x10 <br/> // URG-0x20 <br/> // ace- 0x40 <br/> // CWR-0x80 </P> <p> ushortwindows; // 16-bit window size <br/> ushortchecksum; // 16-bit checksum <br/> ushorturgentpointer; // 16-bit emergency data offset <br/>} tcpheader, * ptcpheader; </P> <p> typedef struct _ udpheader <br/> {<br/> ushortsourceport; // source port number <br/> ushortdestinationport; // destination port number <br/> ushortlen; // packet length <br/> ushortchecksum; // checksum <br/>} udpheader, * pudpheader; </P> <p> # endif // _ protoinfo_h __
//////////////////////////////////////// //// // <Br/> // comm. CPP file </P> <p> # include <winsock2.h> <br/> # include <windows. h> <br/> # include "ws2tcpip. H "</P> <p> # include" Comm. H "</P> <p> ushort checksum (ushort * buff, int size) <br/>{< br/> unsigned long cksum = 0; <br/> while (size> 1) <br/> {<br/> cksum + = * buff ++; <br/> size-= sizeof (ushort ); <br/>}< br/> // It is an odd number <br/> If (size) <br/> {<br/> cksum + = * (uchar *) Bu Ff; <br/>}< br/> // Add the 32-bit chsum high 16 bits and low 16 bits, then, return the inverse result <br/> cksum = (cksum> 16) + (cksum & 0 xFFFF); <br/> cksum + = (cksum> 16 ); <br/> return (ushort )(~ Cksum); <br/>}</P> <p> bool setttl (socket S, int nvalue) <br/>{< br/> int ret = :: setsockopt (S, ipproto_ip, ip_ttl, (char *) & nvalue, sizeof (nvalue); <br/> return ret! = Socket_error; <br/>}</P> <p> bool setTimeout (socket S, int ntime, bool brecv) <br/>{< br/> int ret =:: setsockopt (S, sol_socket, <br/> brecv? So_rcvtimeo: so_sndtimeo, (char *) & ntime, sizeof (ntime); <br/> return ret! = Socket_error; <br/>}< br/>
//////////////////////////////////////// /// <Br/> // Ping. CPP file </P> <p> # include ".. /common/initsock. H "<br/> # include ".. /common/protoinfo. H "<br/> # include ".. /common/Comm. H "</P> <p> # include <stdio. h> </P> <p> cinitsock thesock; </P> <p> typedef struct icmp_hdr <br/>{< br/> unsigned char icmp_type; // Message Type <br/> unsigned char icmp_code; // Code <br/> unsigned short icmp_checksum; // checksum </P> <p> // The echo header is shown below <br/> unsi Gned short icmp_id; // ID used to uniquely identify the request, usually set to process id <br/> unsigned short icmp_sequence; // serial number <br/> unsigned long icmp_timestamp; // timestamp <br/>}icmp_hdr, * picmp_hdr; </P> <p> int main () <br/>{< br/> // destination IP address, that is, the IP address to ping <br/> char szdestip [] = "119.147.15.13 "; // 127.0.0.1 </P> <p> // create the original set of characters <br/> socket Sraw =: socket (af_inet, sock_raw, ipproto_icmp ); </P> <p> // set the receiving timeout <br/> setTimeout (Sraw, 1000, true); </P> <p>/ /Set the destination address <br/> sockaddr_in DEST; <br/> DeST. sin_family = af_inet; <br/> DeST. sin_port = htons (0); <br/> DeST. sin_addr.s_un.s_addr = inet_addr (szdestip); </P> <p> // create an ICMP packet <br/> char buff [sizeof (icmp_hdr) + 32]; <br/> icmp_hdr * picmp = (icmp_hdr *) Buff; </P> <p> // enter the ICMP packet data, request an ICMP echo <br/> picmp-> icmp_type = 8; <br/> picmp-> icmp_code = 0; <br/> picmp-> icmp_id = (ushort ):: getcurrentprocessid (); <br/> picmp-> IC Mp_checksum = 0; <br/> picmp-> icmp_sequence = 0; </P> <p> // fill in the data section, can be any <br/> memset (& buff [sizeof (icmp_hdr)], 'E', 32 ); </P> <p> // start sending and receiving ICMP packets <br/> ushortnseq = 0; <br/> char recvbuf [1024]; <br/> sockaddr_in from; <br/> int nlen = sizeof (from); <br/> while (true) <br/> {<br/> static int ncount = 0; <br/> int nret; </P> <p> // Ping Times <br/> If (ncount ++ = 1000) <br/> break; </P> <p> picmp-> icmp_checksum = 0; <br/> PIC MP-> icmp_timestamp =: gettickcount (); <br/> picmp-> icmp_sequence = nseq ++; <br/> picmp-> icmp_checksum = checksum (ushort *) buff, sizeof (icmp_hdr) + 32); <br/> nret =: sendto (Sraw, buff, sizeof (icmp_hdr) + 32, 0, (sockaddr *) & DEST, sizeof (DEST); <br/> If (nret = socket_error) <br/> {<br/> printf ("sendto () failed: % d/N ",: wsagetlasterror (); <br/> return-1; <br/>}< br/> nret =: recvfrom (Sraw, recvbu F, 1024, 0, (sockaddr *) & from, & nlen); <br/> If (nret = socket_error) <br/>{< br/> If (:: wsagetlasterror () = wsaetimedout) <br/>{< br/> printf ("timed out/N"); <br/> continue; <br/>}< br/> printf ("recvfrom () failed: % d/N",: wsagetlasterror (); <br/> return-1; <br/>}</P> <p> // The ICMP packets received are parsed below. <br/> int ntick =: gettickcount (); <br/> If (nret <sizeof (ipheader) + sizeof (icmp_hdr) <br/>{< br/> printf ("too Few bytes from % s/n ",: inet_ntoa (from. sin_addr); <br/>}</P> <p> // the received data contains an IP header, which is 20 bytes in size, therefore, add 20 to obtain the ICMP header <br/> // (icmp_hdr *) (recvbuf + sizeof (ipheader); <br/> icmp_hdr * precvicmp = (icmp_hdr *) (recvbuf + 20); <br/> If (precvicmp-> icmp_type! = 0) // echo <br/>{< br/> printf ("nonecho type % d recvd/N", precvicmp-> icmp_type ); <br/> return-1; <br/>}</P> <p> If (precvicmp-> icmp_id! =: Getcurrentprocessid () <br/>{< br/> printf ("someone else's packet! /N "); <br/> return-1; <br/>}</P> <p> printf (" % d bytes returned from % s :", inet_ntoa (from. sin_addr), nret); <br/> printf ("packet serial number = % d. /t ", precvicmp-> icmp_sequence); <br/> printf (" latency: % d ms ", ntick-precvicmp-> icmp_timestamp ); <br/> printf ("/N"); </P> <p> // The message is sent once every second. <br/>: Sleep (1000 ); <br/>}< br/> return 0; <br/>}</P> <p>
2. Open omnipeek, run the program, and capture the package as follows:
3. Source Code:
Network Disk download: http://www.rayfile.com/files/d828bc5e-9120-11de-bb76-0014221b798a/