Come creare un socket TCP connettersi utilizzando C a una porta predefinita
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.
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.