- 1. IcmpSendEcho
- 1. Parameters
- 2. Return value
- 2. Work with ICMP
- 3. Conclusion
- 4. Video
Immediately I want to upset you, dear readers. Qt does not have the functionality to work with the ICMP protocol and therefore have to use for this purpose API target operating system. However, this is not surprising. The ICMP protocol is a low-level protocol, and to work with it requires the use of raw sockets, which are not implemented in Qt.
But this is not a particular problem, because the main target platform has the necessary API to implement ping packages. For example Microsoft provides the simple use of ICMP protocol based IcmpSendEcho function.
IcmpSendEcho
The IcmpSendEcho function sends an IPv4 ICMP echo request and returns any echo response replies. The call returns when the time-out has expired or the reply buffer is filled.
DWORD IcmpSendEcho( _In_ HANDLE IcmpHandle, _In_ IPAddr DestinationAddress, _In_ LPVOID RequestData, _In_ WORD RequestSize, _In_opt_ PIP_OPTION_INFORMATION RequestOptions, _Out_ LPVOID ReplyBuffer, _In_ DWORD ReplySize, _In_ DWORD Timeout );
Parameters
IcmpHandle
[in]
The open handle returned by the
IcmpCreateFile
function.
DestinationAddress
[in]
The IPv4 destination address of the echo request, in the form of an
IPAddr
structure.
RequestData
[in]
A pointer to a buffer that contains data to send in the request.
RequestSize
[in]
The size, in bytes, of the request data buffer pointed to by the
RequestData
parameter.
RequestOptions
[in, optional]
A pointer to the IP header options for the request, in the form of an
IP_OPTION_INFORMATION
structure. On a 64-bit platform, this parameter is in the form for an
IP_OPTION_INFORMATION32
structure.
This parameter may be NULL if no IP header options need to be specified.
ReplyBuffer
[out]
A buffer to hold any replies to the echo request. Upon return, the buffer contains an array of
ICMP_ECHO_REPLY
structures followed by the options and data for the replies. The buffer should be large enough to hold at least one
ICMP_ECHO_REPLY
structure plus
RequestSize
bytes of data.
On a 64-bit platform, upon return the buffer contains an array of ICMP_ECHO_REPLY32 structures followed by the options and data for the replies.
ReplySize
[in]
The allocated size, in bytes, of the reply buffer. The buffer should be large enough to hold at least one
ICMP_ECHO_REPLY
structure plus
RequestSize
bytes of data. On a 64-bit platform, The buffer should be large enough to hold at least one
ICMP_ECHO_REPLY32
structure plus
RequestSize
bytes of data.
This buffer should also be large enough to also hold 8 more bytes of data (the size of an ICMP error message).
Timeout
[in]
The time, in milliseconds, to wait for replies.
Return value
The IcmpSendEcho function returns the number of ICMP_ECHO_REPLY or ICMP_ECHO_REPLY32 structures stored in the ReplyBuffer . The status of each reply is contained in the structure. If the return value is zero, call GetLastError for additional error information.
If the function fails, the extended error code returned by GetLastError can be one of the following values.
- ERROR_INSUFFICIENT_BUFFER - The data area passed to a system call is too small. This error is returned if the ReplySize parameter indicates that the buffer pointed to by the ReplyBuffer parameter is too small.
- ERROR_INVALID_PARAMETER - An invalid parameter was passed to the function. This error is returned if the IcmpHandle parameter contains an invalid handle. This error can also be returned if the ReplySize parameter specifies a value less than the size of an ICMP_ECHO_REPLY or ICMP_ECHO_REPLY32 structure.
- ERROR_NOT_ENOUGH_MEMORY - Not enough memory is available to complete the operation.
- ERROR_NOT_SUPPORT - The request is not supported. This error is returned if no IPv4 stack is on the local computer.
- IP_BUF_TOO_SMALL - The size of the ReplyBuffer specified in the ReplySize parameter was too small.
- Other - Use FormatMessage to obtain the message string for the returned error.
Work with ICMP
IcmpSendEcho function sends an ICMP echo request to the specified address and returns the number of received and saved responses ReplyBuffer . IcmpSendEcho function is a synchronous function and returns the value after the end of the waiting time for an answer. If zero is returned, to obtain extended information call the GetLastError function.
In order to use this part of WinAPI, you must register the following two lines to the .Pro project file:
LIBS += -lws2_32 LIBS += -liphlpapi
And also connect the following libraries:
#include "winsock2.h" #include "iphlpapi.h" #include "icmpapi.h"
The main application window
In order to become familiar with the ICMP protocol will create a window with the following interface will be displayed where a response to requests, the IP-address and the start button.
widget.h
Apart from the key slot ads you are not able to see anything interesting, but nevertheless bring a header file.
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QDebug> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private slots: void on_pushButton_clicked(); private: Ui::Widget *ui; }; #endif // WIDGET_H
widget.cpp
And here the most interesting. At the touch of a button We will ping the selected contact IP-address. For beauty solutions I introduced validation of IP-addresses in lineEdit field.
#include "widget.h" #include "ui_widget.h" #include "winsock2.h" #include "iphlpapi.h" #include "icmpapi.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); // We validate the input data IP-addresses QString ipRange = "(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])"; QRegExp ipRegex ("^" + ipRange + "\\." + ipRange + "\\." + ipRange + "\\." + ipRange + "$"); QRegExpValidator *ipValidator = new QRegExpValidator(ipRegex, this); ui->lineEdit->setValidator(ipValidator); } Widget::~Widget() { delete ui; } void Widget::on_pushButton_clicked() { // We declare variables HANDLE hIcmpFile; // Handler unsigned long ipaddr = INADDR_NONE; // Destination address DWORD dwRetVal = 0; // Number of replies char SendData[32] = "Data Buffer"; // The buffer data being sent LPVOID ReplyBuffer = NULL; // buffer replies DWORD ReplySize = 0; // Buffer Size responses // Set the IP-address of the field qlineEdit ipaddr = inet_addr(ui->lineEdit->text().toStdString().c_str()); hIcmpFile = IcmpCreateFile(); // create a handler // Select the buffer memory responses ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData); ReplyBuffer = (VOID*) malloc(ReplySize); // Call the ICMP echo request function dwRetVal = IcmpSendEcho(hIcmpFile, ipaddr, SendData, sizeof(SendData), NULL, ReplyBuffer, ReplySize, 1000); // We create a row in which we write the response message QString strMessage = ""; if (dwRetVal != 0) { // The structure of the echo response PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer; struct in_addr ReplyAddr; ReplyAddr.S_un.S_addr = pEchoReply->Address; strMessage += "Sent icmp message to " + ui->lineEdit->text() + "\n"; if (dwRetVal > 1) { strMessage += "Received " + QString::number(dwRetVal) + " icmp message responses \n"; strMessage += "Information from the first response: "; } else { strMessage += "Received " + QString::number(dwRetVal) + " icmp message response \n"; strMessage += "Information from the first response: "; } strMessage += "Received from "; strMessage += inet_ntoa( ReplyAddr ); strMessage += "\n"; strMessage += "Status = " + pEchoReply->Status; strMessage += "Roundtrip time = " + QString::number(pEchoReply->RoundTripTime) + " milliseconds \n"; } else { strMessage += "Call to IcmpSendEcho failed.\n"; strMessage += "IcmpSendEcho returned error: "; strMessage += QString::number(GetLastError()); } ui->textEdit->setText(strMessage); // Display information about the received data free(ReplyBuffer); // frees memory }
Conclusion
As a result, you should have an application that will ping the selected IP-address.
Без строки
в заголовочном файле не работает валидатор.