2008-10-15 9 views
9

Tengo una pregunta muy simple. Quiero probar si un puerto en particular está actualmente en uso o no. Para esto, quiero vincular un socket TCP al puerto, si la conexión es rechazada significa que el puerto está en uso y si no significa que el puerto es libre.Cómo crear una conexión de socket TCP usando C a un puerto predefinido

¿Puede alguien decirme cómo puedo escribir el código de socket TCP en C? Estoy en una plataforma solaris.

Sé que es muy básico. Pero aprecio tu ayuda. Gracias por adelantado.

+3

¿Es esta tarea? –

Respuesta

12

La función de llamada para vincular devolverá -1 si hay un error. Esto incluye el caso donde la dirección ya está en uso.

#include <stdio.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 

#define PORT 12345 

int main() 
{ 
    struct sockaddr_in addr; 
    int fd; 

    fd = socket(AF_INET, SOCK_STREAM, 0); 
    if(fd == -1) 
    { 
     printf("Error opening socket\n"); 
     return -1; 
    } 

    addr.sin_port = htons(PORT); 
    addr.sin_addr.s_addr = 0; 
    addr.sin_addr.s_addr = INADDR_ANY; 
    addr.sin_family = AF_INET; 

    if(bind(fd, (struct sockaddr *)&addr,sizeof(struct sockaddr_in)) == -1) 
    { 
     printf("Error binding socket\n"); 
     return -1; 
    } 

    printf("Successfully bound to port %u\n", PORT); 
} 
-1

Es posible que desee ver el código fuente de netstat. Creo que también hay un netstat en Solaris.

-1

¿Quiere comprobar si el puerto en particular está actualmente en uso? (y realmente no necesita hacer un programa). Si es así, puede utilizar telnet:

puerto host telnet

Si la conexión falla, no está en uso. Si se conecta y espera la entrada de usted, está en uso :)

+1

Esto solo le dirá si hay un puerto de escucha en ese puerto, no si está abierto. –

8

Depende ligeramente de exactamente lo que está tratando de probar.

El uso de bind() en la forma sugerida por joelc le dirá si el puerto está abierto en cualquier interfaz en su máquina. Aunque debe ser minucioso, no solo debe verificar el valor de retorno desde bind(), sino también marcar errno == EADDRINUSE.

es decir. (modificación del código de joelc)


if(bind(socket, (struct sockaddr *)&sin,sizeof(struct sockaddr_in)) == -1) 
{ 
    if(errno == EADDRINUSE) 
    { 
     // handle port already open case 
    } 
    else 
    { 
     // handle other errors 
    } 
} 

Cambiando la dirección utilizada en la línea: ej.


    sin.sin_addr.s_addr = inet_addr("192.168.1.1"); 

... puede probar si un puerto está disponible en una interfaz específica.

Tenga en cuenta que esta no es una prueba perfecta para el estado del puerto. Si otro proceso tenía el puerto abierto y se terminó antes de cerrar con gracia el puerto (es decir, antes de llamar al close() en el socket), entonces generalmente obtendrá el mismo error EADDRINUSE. (dependiendo de si la opción SO_REUSEADDR se había fijado en el zócalo)

(nota al margen: a menos que su aplicación de prueba se está ejecutando con privilegios suficientes usted no será capaz de unirse() a cualquiera de los puertos por debajo de 1024)

Como lo sugirió Anonymous, también puede consultar netstat. Esto le dará toda la información que puede obtener al llamar repetidamente bind() mucho más rápido y sin ninguno de los efectos secundarios (como que no tiene que vincularse realmente a los puertos, lo que los haría inutilizables para cualquier otro proceso).) Simplemente llamando al netstat -a --numeric-ports -t y analizando la salida debería darle todo lo que está buscando.

Sin embargo, un comentario sobre la sugerencia de moogs: llamar a telnet en cada puerto solo le indicará si un socket está escuchando en ese puerto, no si realmente está abierto.

Cuestiones relacionadas