zocalos zocalo tipos socket que procesador informatica actuales c network-programming

zocalo - tipos de socket intel y amd



C: tiempo de espera de conexión del socket (5)

En Linux también puedes usar:

struct timeval timeout; timeout.tv_sec = 7; // after 7 seconds connect() will timeout timeout.tv_usec = 0; setsockopt(fd, SO_SNDTIMEO, &timeout, sizeof(timeout)); connect(...)

No olvide borrar SO_SENDTIMEO después de connect() si no lo necesita.

Tengo un programa simple para verificar si un puerto está abierto, pero quiero acortar la duración del tiempo de espera en la conexión de socket porque el valor predeterminado es demasiado largo. Aunque no estoy seguro de cómo hacerlo. Aquí está el código:

#include <sys/socket.h> #include <sys/time.h> #include <sys/types.h> #include <arpa/inet.h> #include <netinet/in.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <netdb.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main(int argc, char **argv) { u_short port; /* user specified port number */ char addr[1023]; /* will be a copy of the address entered by u */ struct sockaddr_in address; /* the libc network address data structure */ short int sock = -1; /* file descriptor for the network socket */ if (argc != 3) { fprintf(stderr, "Usage %s <port_num> <address>", argv[0]); return EXIT_FAILURE; } address.sin_addr.s_addr = inet_addr(argv[2]); /* assign the address */ address.sin_port = htons(atoi(argv[2])); /* translate int2port num */ sock = socket(AF_INET, SOCK_STREAM, 0); if (connect(sock,(struct sockaddr *)&address,sizeof(address)) == 0) { printf("%i is open/n", port); } close(sock); return 0; }


Establezca el socket como no bloqueante, y use select() (que toma un parámetro de tiempo de espera). Si un socket sin bloqueo está intentando conectarse, entonces select() indicará que el socket es grabable cuando el connect() finalice (ya sea con éxito o sin éxito). A continuación, usa getsockopt() para determinar el resultado de connect() :

int main(int argc, char **argv) { u_short port; /* user specified port number */ char *addr; /* will be a pointer to the address */ struct sockaddr_in address; /* the libc network address data structure */ short int sock = -1; /* file descriptor for the network socket */ fd_set fdset; struct timeval tv; if (argc != 3) { fprintf(stderr, "Usage %s <port_num> <address>/n", argv[0]); return EXIT_FAILURE; } port = atoi(argv[1]); addr = argv[2]; address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr(addr); /* assign the address */ address.sin_port = htons(port); /* translate int2port num */ sock = socket(AF_INET, SOCK_STREAM, 0); fcntl(sock, F_SETFL, O_NONBLOCK); connect(sock, (struct sockaddr *)&address, sizeof(address)); FD_ZERO(&fdset); FD_SET(sock, &fdset); tv.tv_sec = 10; /* 10 second timeout */ tv.tv_usec = 0; if (select(sock + 1, NULL, &fdset, NULL, &tv) == 1) { int so_error; socklen_t len = sizeof so_error; getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &len); if (so_error == 0) { printf("%s:%d is open/n", addr, port); } } close(sock); return 0; }


Este artículo podría ayudar: http://developerweb.net/viewtopic.php?id=3196 . Parece que pones el zócalo en modo sin bloqueo hasta que te hayas conectado, y luego lo vuelves a poner en modo de bloqueo una vez que se establece la conexión.


Este ha parametrizado ip, port, timeout en segundos, maneja los errores de conexión y le da tiempo de conexión en milisegundos:

#include <sys/socket.h> #include <sys/time.h> #include <sys/types.h> #include <arpa/inet.h> #include <netinet/in.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <netdb.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <time.h> int main(int argc, char **argv) { struct sockaddr_in addr_s; char *addr; short int fd=-1; int port; fd_set fdset; struct timeval tv; int rc; int so_error; socklen_t len; struct timespec tstart={0,0}, tend={0,0}; int seconds; if (argc != 4) { fprintf(stderr, "Usage: %s <ip> <port> <timeout_seconds>/n", argv[0]); return 1; } addr = argv[1]; port = atoi(argv[2]); seconds = atoi(argv[3]); addr_s.sin_family = AF_INET; // utilizzo IPv4 addr_s.sin_addr.s_addr = inet_addr(addr); addr_s.sin_port = htons(port); clock_gettime(CLOCK_MONOTONIC, &tstart); fd = socket(AF_INET, SOCK_STREAM, 0); fcntl(fd, F_SETFL, O_NONBLOCK); // setup non blocking socket // make the connection rc = connect(fd, (struct sockaddr *)&addr_s, sizeof(addr_s)); if ((rc == -1) && (errno != EINPROGRESS)) { fprintf(stderr, "Error: %s/n", strerror(errno)); close(fd); return 1; } if (rc == 0) { // connection has succeeded immediately clock_gettime(CLOCK_MONOTONIC, &tend); printf("socket %s:%d connected. It took %.5f seconds/n", addr, port, (((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) - ((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec))); close(fd); return 0; } /*else { // connection attempt is in progress } */ FD_ZERO(&fdset); FD_SET(fd, &fdset); tv.tv_sec = seconds; tv.tv_usec = 0; rc = select(fd + 1, NULL, &fdset, NULL, &tv); switch(rc) { case 1: // data to read len = sizeof(so_error); getsockopt(fd, SOL_SOCKET, SO_ERROR, &so_error, &len); if (so_error == 0) { clock_gettime(CLOCK_MONOTONIC, &tend); printf("socket %s:%d connected. It took %.5f seconds/n", addr, port, (((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) - ((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec))); close(fd); return 0; } else { // error printf("socket %s:%d NOT connected: %s/n", addr, port, strerror(so_error)); } break; case 0: //timeout fprintf(stderr, "connection timeout trying to connect to %s:%d/n", addr, port); break; } close(fd); return 0; }


Las respuestas sobre el uso de select() / poll() son correctas y el código debe escribirse de esta manera para ser portátil.

Sin embargo, como estás en Linux, puedes hacer esto:

int synRetries = 2; // Send a total of 3 SYN packets => Timeout ~7s setsockopt(fd, IPPROTO_TCP, TCP_SYNCNT, &synRetries, sizeof(synRetries));

Ver man 7 tcp y man setsockopt .

Utilicé esto para acelerar el tiempo de espera de conexión en un programa que necesitaba parchar rápidamente. Hackear el tiempo de espera a través de select() / poll() no era una opción.