Paramètre IPv4/IPv6, l'adresse et le port d'un sockaddr_storage structure
Je suis le portage d'une IPv4 application à un AF-indépendant de la base de code(il devrait travailler avec les protocoles IPv4 et IPv6). Maintenant, je suis en utilisant sockaddr_storage partout où je peux, cependant maintenant, je dois mettre(remplir) une sockaddr_storage. Mais je ne sais pas quelle est la manière correcte est. Le code précédent a été de:
//defined in data_socket.h
struct sockaddr_in laddr;
Maintenant il y a cette fonction qui définit sin_addr et sin_port:
void DataSocket::SetLocalAddr(const char *addr, const int port)
{
this->laddr.sin_port = htons(port);
if(addr != NULL)
this->laddr.sin_addr.s_addr = inet_addr(addr);
else
this->laddr.sin_addr.s_addr = inet_addr("0.0.0.0");
}
Comme vous le voyez c'est le style ancien(utilise IPv4).
Maintenant, mes modifications sont ci-dessous. Tout d'abord j'ai changé sockaddr_in
à sockaddr_storage
//defined in data_socket.h
struct sockaddr_storage laddr;
Puis j'ai changé le code ci-dessus à l'appui de IPv4 et IPv6:
void DataSocket::SetLocalAddr(const char *addr, const int port)
{
switch (this->GetAddrFamily(addr)) {
case AF_INET:
(struct sockaddr_in *) this->laddr.sin_port = htons(port);
if(addr != NULL)
inet_pton(AF_INET, addr, (struct sockaddr_in *) this->laddr.sin_addr);
else
inet_pton(AF_INET, "0.0.0.0", (struct sockaddr_in *) this->laddr.sin_addr);
break;
case AF_INET6:
(struct sockaddr_in6 *) this->laddr.sin6_port = htons(port);
if(addr != NULL)
inet_pton(AF_INET6, addr, (struct sockaddr_in6 *) this->laddr.sin6_addr);
else
inet_pton(AF_INET6, "0:0:0:0:0:0:0:0", (struct sockaddr_in6 *) this->laddr.sin6_addr);
break;
default:
return NULL;
}
}
Où GetAddrFamily()
est:
int DataSocket::GetAddrFamily(const char *addr)
{
struct addrinfo hints, *res;
int status, result;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((status = getaddrinfo(addr, 0, &hints, &res)) != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return false;
}
result = res->ai_family; //This might be AF_INET, AF_INET6,etc..
freeaddrinfo(res); //We're done with res, free it up
return result;
}
Il semble que mon chemin est complexe. Est-ce la bonne façon de le faire? Parce que j'ai changé sockaddr_in à sockaddr_storage, en fait je veux juste l'inverse de cette question: Obtenir de l'adresse IPV4 à partir d'une structure sockaddr
J'essaie de trouver la meilleure solution, par exemple ici: http://www.kame.net/newsletter/19980604/ il déclare ne jamais utiliser inet_ntop()
et inet_pton()
, cependant, certains d'autres(comme le Beej du réseau tutoriel) dit que inet_ntop()
et inet_pton()
doit être utilisé pour IPv6 en fonction de l'application.
Est ma façon de la mise en œuvre correcte ou dois-je le changer?
boost::asio::ip::address
, il les résumés loin boost::asio::ip::address_v4
et boost::asio::ip::address_v6
.Laissez-moi savoir lors de la C des gains de fonctions membres.
oups désolé pour le
c
tagOriginalL'auteur Fatih Arslan | 2012-07-12
Vous devez vous connecter pour publier un commentaire.
Je recommande fortement de laisser
getaddrinfo
faire tout le levage lourd, par exemple.memcpy(&this->laddr, res->ai_addr, res->ai_addrlen);
ligne. Leres->ai_addr
est une structure sockaddr, je suppose qu'il est automatiquement converti ensockaddr_in
ousockaddr_in6
? Comment il est stocké dansthis->laddr
(parce quethis->laddr
est unsockaddr_storage
structure)?Et je suppose que je devrais utiliser
port_buffer
au lieu deport
dansgetaddrinfo
, parce quegetaddrinfo()
à l'exception d'un const char *(aka chaîne)?res->ai_addr
points à une variante destruct sockaddr
, soitsockaddr_in
ousockaddr_in6
. Il n'y a pas de conversion en cours, la structure est simplement copié.struct sockaddr_storage
est d'une taille et d'une mise en page permettant d'être jeté dans l'une quelconque dessockaddr
variantes, qui part d'un en-tête commun. re: passage d'une chaîne comme le port, je n'aurais pas pris la peine, mais c'est votre code. (aussi, la correction d'une faute, getaddrinfo était censé être le tampon)J'ai demandé parce que je vais utiliser le
this->laddr
structure dans une autre fonction. Cependant, je net know which structure it is based on. I've initially set it as
sockaddr_storage. Does it mean I have to check now
this->laddr.ss_family` (supposons que c'estsockaddr_storage) and cast it to
sockaddr_in " ousockaddr_in6
si je veux l'utiliser dans d'autres fonctions? Ou dois-je vérifier pourthis->laddr.sa_family
(parce que c'est une simplesockaddr
structure)?La vérification de
laddr.ss_family
et la vérification de(struct sockaddr)laddr.sa_family
sont identiques. Pour la plupart, vous pouvez simplement transmettre lestruct sockaddr_storage
autour de, moulagesockaddr
(ou le _en/in6 variantes) en cas de besoin.OriginalL'auteur Hasturkun
Si je comprends bien, vous êtes casting
this
pour le premier membre? ne le faites pas, le nom de la membre de.Je voudrais aussi rendre plus facile à lire par l'introduction d'un
{}
portée et une variable locale pour les deux cas, quelque chose comme:Une puisque vous êtes à l'aide de C++ et pas en C pour cela, utiliser le C++ style jette. C-style jette en C++ est trop ambigu.
OriginalL'auteur Jens Gustedt