Как выполнить tcp ping сервера?

 

Из-за того что по разным причинам ICMP пинг может несработать, может понадобиться TCP пинг. О причинах разглагольствовать небуду, сразу приведу текст программы на си:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <netdb.h>

void error(char *msg) {
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[]) {
    int ret,i;
    struct sockaddr_in serveraddr;
    struct hostent *server;
    char *ptr;
    fd_set fdset;
    int sockfd;
    struct timeval s_tv;
    struct timeval tv;
    // first argument hostname:port
    char *hostname; 	//host
    int portnumb;		//port  
    //check number of command line arguments
    if (argc != 2) {
       fprintf(stderr,"usage: %s <server>\n", argv[0]);
       return 1;
    }
    hostname = argv[1];
    ptr = hostname;
    //check a statement - hostname:port
    while( *ptr !=':') {
    	if( (!isalpha(*ptr)) && (!isdigit(*ptr)) && (*ptr != '.')) {
    		fprintf(stderr,"write: hostname:port\n");
    		return 1;
    	}
    	ptr++;
    }
    *ptr++ = 0; //passing ':' !write to argv[1]!
    portnumb = atoi(ptr);
    /**************************************************************/
    /* socket: create the socket */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)        error("ERROR opening socket");
    if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) error("ERROR fcntl"); 
    /* gethostbyname: get the server's DNS entry */ 
    server = gethostbyname(hostname); 
    if (server == NULL) { 
    fprintf(stderr,"ERROR, no such host as %s\n", hostname); return 1; } 
    /* build the server's Internet address */ 
    bzero((char *) &serveraddr, sizeof(serveraddr)); 
    serveraddr.sin_family = AF_INET; 
    bcopy((char *)server->h_addr,(char *)&serveraddr.sin_addr.s_addr, server->h_length);
    serveraddr.sin_port = htons(portnumb);
    
    /*here, there is a mesuring of the ping.*/
    /*you can just use select's tv argument for counting timeout, 
    but then you're lossing execution time of several instruction, 
    which can be significant on miniPC architectures*/
    gettimeofday(&s_tv,NULL);	//get start timestamp
    connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
    FD_ZERO(&fdset);
    FD_SET(sockfd, &fdset);
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    //select for the sockfd while some event or timeout yet happend
    if (select(sockfd + 1, NULL, &fdset, NULL, &tv)!=1) 
    	return 1; //timeout or error.. doesn't matter
    gettimeofday(&tv,NULL);	//catch finish timestamp
   
    tv.tv_sec -= s_tv.tv_sec;
    if(s_tv.tv_usec > tv.tv_usec)	{
    	tv.tv_usec += 1000000;
    	tv.tv_sec --;
    }
    tv.tv_usec -= s_tv.tv_usec;
    printf("time=%d.%03d ms\n", 
		(uint32_t) ((1000*tv.tv_sec) + (tv.tv_usec/1000)), 
		(uint32_t) (tv.tv_usec%1000) );

    return 0;
}

Компиляция

Я пользуюсь linux, на windows этот код скорее всего тоже заработает, возможно что то изменить нужно будет (вывод с «\n» точно нужно поменять). Команда для компиляции:

 ~$gcc tcpping.c -o tcpping 

Использование

 
~$./tcpping google.ru:80
time=1.049 ms
~$

 
~$./tcpping 192.168.0.175:80
time=0.340 ms
~$

 
~$./tcpping google.ru:8080
~$

 
~$./tcpping google.ru:8080 || echo timeout
timeout
~$

 
~$./tcpping google.ru:80 || echo timeout
time=0.977 ms
~$

 
~$while :;do ./tcpping ny.gov:22 && sleep 1; done 
time=250.544 ms
time=250.159 ms
time=250.442 ms
time=250.470 ms
time=250.483 ms
time=250.536 ms
time=250.511 ms
...

Как это работает

Для tcp ping используется оссобенность TCP протокола: для того что бы установить соединение с сервером должна пройти процедура — establishment. Чтобы стало понятней объясню простыми словами:

  1. Клиент отправляет серверу сообщение, что хочет установить соединение для передачи данных.
  2. Когда сервер получает это сообщение, он отправляет ответ — подтверждение и ответный запрос. Когда клиент получает ответ от сервера, то возникает сигнал — соединение установленно или отказанно.
  3. Далее в случае если клиент получил ответ от сервера, то он сразу же отправляет подтверждение серверу, после получения которого и у сервера возникнет сигнал — соединение установленно.

В выше приведенной программе измеряется время прохождение первых двух сообщений, от клиента к серверу и от сервера к клиенту.

Пинг возможен только в том случае, если соответствующий порт сервера отвечает на запросы. При этом данный порт вполне может быть закрыт файерволом сервера. Если ответа от сервера неприходит, то отработает таймаут. Кстати таймаут в приведенном коде равен 1 секунде, можете изменить по своему усмотрению (71,72 строки).
На большинстве серверов все порты как правило закрыты кроме нескольких. Но даже закрытые порты в большинстве случаев отвечают (отказом), так что проблем с пингом небудет. Информация о том открыт порт или закрыт программа не выдает.

Оставьте первый комментарий к статье «Как выполнить tcp ping сервера?»

Добавить комментарий