Domanda

Ho una domanda molto semplice. Voglio verificare se una determinata porta è attualmente in uso o meno. Per questo, voglio associare un socket TCP alla porta, se la connessione viene rifiutata significa che la porta è in uso e in caso contrario significa che la porta è libera.

Qualcuno può dirmi come posso scrivere il codice socket TCP in C? Sono su una piattaforma Solaris.

So che è molto semplice. Ma apprezzo il tuo aiuto. Grazie in anticipo.

È stato utile?

Soluzione

La funzione di chiamata a bind restituirà -1 in caso di errore. Ciò include il caso in cui l'indirizzo è già in 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);
}

Altri suggerimenti

Dipende leggermente da cosa stai provando a testare.

L'uso di bind () nel modo suggerito da joelc ti dirà se la porta è aperta su qualsiasi sulla tua macchina. Anche se per essere accurato, non dovresti solo controllare il valore di ritorno da bind () , ma anche controllare errno == EADDRINUSE .

es. (modifica del codice di joelc)


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

Modificando l'indirizzo utilizzato nella riga: ad es.


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

... puoi verificare se una porta è disponibile su un'interfaccia specifica.

Tuttavia, tieni presente che questo non è un test perfetto per lo stato della porta. Se un altro processo ha aperto la porta ed è stato terminato prima che chiudesse con grazia la porta (cioè prima di chiamare close () sul socket) di solito otterrai lo stesso EADDRINUSE errore. (a seconda che l'opzione SO_REUSEADDR sia stata impostata sul socket)

(nota a margine: a meno che l'applicazione di test non sia in esecuzione con privilegi sufficienti, non sarà possibile associare () a nessuna porta inferiore a 1024)

Come suggerito da Anonymous, puoi anche dare un'occhiata a netstat . Questo ti fornirà tutte le stesse informazioni che puoi ottenere chiamando ripetutamente bind () molto più rapidamente e senza effetti collaterali (come se non dovesse effettivamente legarsi alle porte, che li renderebbe inutilizzabili per qualsiasi altro processo). Basta chiamare netstat -a --numeric-doors -t e analizzare l'output dovrebbe darti tutto quello che stai cercando.

Un commento sul suggerimento di moogs: la chiamata di telnet su ciascuna porta ti dirà solo se un socket è in ascolto su quella porta, non se è effettivamente aperto.

Vuoi solo verificare se la porta particolare è attualmente in uso? (e non è necessario creare un programma). In tal caso, puoi utilizzare telnet:

  

porta host telnet

Se la connessione fallisce, non è in uso. Se si connette e attende input da te, è in uso :)

Potresti voler guardare il codice sorgente di netstat. Credo che ci sia un netstat anche in Solaris.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top