In the previous article, we talked about the simulation of the VC ++ ping command. That is just an example. Click to open the link.
After integrating the code this time, I will do a practical exercise, scan an IP segment, and return all active IP addresses.
To complete this exercise, follow these steps to use code as a programmer.
First, you must verify whether an IP address is active. The Code is as follows:
Bool ipcheck: isipactive (char * ADDR) {// destination IP address, that is, the IP address to ping char * szdestip = ADDR; // 127.0.0.1 // create the original set of characters wsadata; wsastartup (makeword (2, 2), & wsadata); socket Sraw = socket (af_inet, sock_raw, ipproto_icmp); // set the receiving timeout setTimeout (Sraw, 100, true ); // set the target address sockaddr_in DEST; DeST. sin_family = af_inet; DeST. sin_port = htons (0); DeST. sin_addr.s_un.s_addr = inet_addr (szdestip); // create an ICMP packet char Buff [sizeof (icmp_hdr) + 32]; icmp_hdr * picmp = (icmp_hdr *) Buff; // enter the ICMP packet data and request an ICMP echo picmp-> icmp_type = 8; picmp-> icmp_code = 0; picmp-> icmp_id = (ushort) getcurrentprocessid (); picmp-> icmp_checksum = 0; picmp-> icmp_sequence = 0; // fill in the data section, can be any memset (& buff [sizeof (icmp_hdr)], 'E', 32); // start sending and receiving ICMP packets ushort nseq = 0; char recvbuf [1024]; sockaddr_in from; int nlen = sizeof (from); static int Ncount = 0; int nret; picmp-> icmp_checksum = 0; picmp-> icmp_timestamp = gettickcount (); picmp-> icmp_sequence = nseq ++; picmp-> icmp_checksum = checksum (ushort *) buff, sizeof (icmp_hdr) + 32); nret = sendto (Sraw, buff, sizeof (icmp_hdr) + 32, 0, (sockaddr *) & DEST, sizeof (DEST); If (nret = socket_error) {printf ("sendto () failed: % d \ n ",:: wsagetlasterror (); Return-1;} nret = recvfrom (Sraw, recvbu F, 1024, 0, (sockaddr *) & from, & nlen); If (nret = socket_error) {If (wsagetlasterror () = wsaetimedout) {printf ("% s timed out \ n", ADDR); Return false;} printf ("recvfrom () failed: % d \ n", wsagetlasterror ()); return false;} // The ICMP packet int ntick =: gettickcount (); If (nret <sizeof (ipheader) + sizeof (icmp_hdr) received is parsed below )) {printf ("too few bytes from % s \ n", inet_ntoa (from. sin_addr);} // the received data contains an IP header. The IP header size is 20 bytes, so add 20 to get the ICMP header // (icmp_hdr *) (recvbuf + sizeof (ipheader); icmp_hdr * precvicmp = (icmp_hdr *) (recvbuf + 20); If (precvicmp-> icmp_type = icmp_type_reach_fail) // echo {printf ("% s reach fail, type % d recvd \ n", ADDR, precvicmp-> icmp_type); Return false;} If (precvicmp-> icmp_id! = Getcurrentprocessid () {printf ("someone else's packet! \ N "); Return false;} printf (" % d bytes returned from % s: ", ADDR, nret); printf (" packet serial number = % d. \ t ", precvicmp-> icmp_sequence); printf (" latency: % d ms ", ntick-precvicmp-> icmp_timestamp); printf (" \ n "); s_array-> insert (ADDR); wsacleanup (); closesocket (Sraw); Return true ;}
This is to scan a specified IP address. To scan multiple IP addresses, you must convert the IP address to an integer to accumulate the IP address.
Unsigned long _ fastcall ipcheck: invertip (unsigned long normalip) {unsigned char B1, B2, B3, B4; b1 = normalip & 0x00ff; b2 = (normalip> 8) & 0x00ff; B3 = (normalip> 16) & 0x00ff; B4 = (normalip> 24) & 0x00ff; Return (b1 <24) | (b2 <16) | (B3 <8) | B4 ;}// void ipcheck: mutiscan (char * s_ip, char * e_ip) {in_addr IA; unsigned long firstip, secondip; int delta; char * ADDR; firstip = inet_addr (s_ip); // any starting address secondip = inet_addr (e_ip ); // any ending address // can be directly incremented or decreased. The address firstip = invertip (firstip); secondip = invertip (secondip); Delta = secondip-firstip; s_array-> initbuf (delta + 1); For (INT I = 0; I <= delta; I ++) {IA. s_un.s_addr = invertip (firstip ++); ADDR = inet_ntoa (IA); // scan isipactive (ADDR );}}
After scanning IP addresses, how can we record and print all active IP addresses? Most people may think of STL. I personally used STL to have a shadow, so I wrote a string array to store the data structure. I know what I wrote, and it is highly flexible. I can write code that meets my needs at any time, so I will post this storage class.
Stringarray. h
# Pragma once // This is a self-Written string storage data structure of a char pointer. It uses arrays and does not use STL because it is not used to STL, class stringarray {public: stringarray (void); stringarray (INT length );~ Stringarray (void); void initbuf (INT length); int insert (char * Str); char * getstring (INT index); char ** wrapbuffer (); int getlength (); void release (); Private: Char ** strbuf; int length; int count ;};
Stringarray. cpp
#include "StdAfx.h"#include "StringArray.h"StringArray::StringArray(void){length = 0;strbuf = NULL;count = 0;}StringArray::StringArray(int length){this->length = length;strbuf = (char **)malloc(sizeof(char *) * length);count = 0;}StringArray::~StringArray(void){Release();}void StringArray::InitBuf(int length){this->length = length;strbuf = (char **)malloc(sizeof(char *) * length);for(int i = 0;i < length;i++)strbuf[i] = NULL;}int StringArray::Insert(char *str){if(str == NULL || count == length)return DEFAULT_ERROR;strbuf[count] = (char *)malloc(sizeof(char) * (strlen(str) + 1));if(strbuf[count] == NULL)return DEFAULT_ERROR;memset(strbuf[count], 0, strlen(str) + 1);memcpy(strbuf[count], str, strlen(str));strbuf[count][strlen(str)] = '\0';count++;return DEFAULT_SUCCESS;}char *StringArray::GetString(int index){if(index > length || index < -1)return NULL;return strbuf[index];}int StringArray::GetLength(){return length;}char **StringArray::WrapBuffer(){return strbuf;}void StringArray::Release(){if(strbuf != NULL){for(int i = 0;i < length;i++){if(strbuf[i] != NULL){free(strbuf[i]);strbuf[i] = NULL;}}free(strbuf);strbuf = NULL;}}
With this, we can implement the main function.
// Scanip. cpp: defines the entry point of the console application. // # Include "stdafx. H "int _ tmain (INT argc, _ tchar * argv []) {If (argc> 3) printf (" error parameter: argc> 3 \ n "); char * param1 = NULL; char * param2 = NULL; ipcheck Si; If (argv [1]! = NULL & argv [2]! = NULL) {param1 = W2C (argv [1]); param2 = W2C (argv [2]); SI. mutiscan (param1, param2);} else if (argv [1]! = NULL) {param1 = W2C (argv [1]); SI. mutiscan (param1, param1);} else {printf ("error parameter \ n"); Return 0;} Char ** rs = SI. getips (); int COUNT = 0; printf ("available IP: \ n"); For (INT I = 0; I <Si. ipcounts (); I ++) {If (RS [I] = NULL) break; printf ("% s \ t", RS [I]); if (COUNT = 3) {COUNT = 0; printf ("\ n") ;}count ++;} If (param1! = NULL) Free (param1); If (param2! = NULL) Free (param2); // system ("pause"); Return 0 ;}
The process is to scan the specified IP segment and display all existing IP addresses.
For example, enter scanip.exe 10.72.0.0 10.72.0.255 under "login ".
Scan a CIDR block within a period of time
Results:
The above is the process of scanning an IP segment