| Uutiset | Koodikirjasto | Wiki | Keskustelut | FAQ | Info |
build connectionneon 25.06.04 01:23 Yhteyden muodostaminen, IPv6 tuki ja paikallisen osoitteen bindaus
#include <sys/types.h> #include <sys/socket.h> #include <sys/uio.h> #include <netinet/in.h> #include <netdb.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> int connect_remote_host(const int socktype, const int addrfamily, const char *target_host, const int target_port, const char *localhost); /** Esimerkki paikallisen osoitteen bindauksesta käytettävään sockettin ja sitten yhdistämisestä etääkoneeseen. Esimerkki toimii myös IPv6 esimerkkinä, koska kaikki on sekä IPv6 että IPv4 yhteensopivaa, riippuen kohdekoneen osoitteesta. Jos kohdekoneella on sekä IPv6 että IPv4 osoite ja ensin esimerkiksi yritetään yhdistää IPv6 osoitteeseen, joka epäonnistuu, yritetään vielä IPv4 osoitetta. Tai jos kohdekoneella on monta IP-osoitetta (multihomed) niin yritetään niin kauan kunnes yhteys onnistuu tai kaikki on kokeiltu läpi. */ /** @param const int socket descriptor referencing the socket @param struct addinfo *hints information about connection @param const char *hostname local hostname to be binded @return int state -1 if bind failed, 0 is successful */ int bind_local_addr(const int sock, struct addrinfo *hints, const char *hostname) { struct addrinfo *res_all, *r; if(getaddrinfo(hostname, NULL, hints, &res_all)) { /* virhe */ return -1; } r = res_all; /* Kopioidaan alkuperäisen pointterin osoite, jotta kyseisen pointterin sisältö voidaan myöhemmin poistaa muistista. */ while(r) { if(bind(sock, r->ai_addr, r->ai_addrlen) == -1) { r = r->ai_next; /* kokeillaan seuraavaa osoitetta */ } else { /* bindaus onnistui */ freeaddrinfo(res_all); return 0; } } freeaddrinfo(res_all); return -1; } /** @param const int socktype the semantics of communication @param const int addrfamily address family AF_INET, AF_INET6, AF_UNSPEC @param const int *target_host hostname to be connected @param const int target_port port at remotehost @param const char *hostname local hostname to be binded @return int socket descriptor referencing the socket */ int connect_remote_host(const int socktype, const int addrfamily, const char *target_host, const int target_port, const char *localhost) { struct addrinfo hints, *res, *ressave; char port_buf[6]; int sock = -1; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = addrfamily; hints.ai_socktype = socktype; sprintf(port_buf,"%d",target_port); /* muutetaan portti stringiksi (liimaamalla) */ /* Koska tarkoitus on tukea myös IPv6 osoitteita, tulee kohdejäjestelmän osoite selvittää ensin, jotta tiedetään kumpaa osoitetyyppiä käytetään paikallisen osoitteen bindauksessa. */ if(getaddrinfo(target_host, port_buf, &hints, &res)) { return -1; } for (ressave = res; res; res = res->ai_next) { if((sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0 ) { continue; } /* Yritetään bindata paikallinen osoite, jos asetettu arvoon NULL saadaan wildcard-tyyppinen käytös. Huomautettakoon, että bindausta yritetään kaikilla sopivilla paikallisilla osoiteilla, mutta vain ensimmäistä toimivaa käytetään yhteysyrityksissä, eikä kaikkia. */ if(bind_local_addr(sock,&hints,localhost) == -1) { /* virhe */ close(sock); sock = -1; continue; } /* yritetään yhdistää kohdejäjestelmään */ if(connect(sock, res->ai_addr, res->ai_addrlen) < 0) { /* virhe */ close(sock); sock = -1; continue; } /* Jos silmukka on suoritettu loppuun asti ei virheitä ole esiintynyt. Poistutaan silmukasta. */ break; } freeaddrinfo(ressave); return sock; } |
![]() Haku
|