私は以下のようなコードを書いています。このコードは、PASSIVE_SOCKET(サーバーがソケットにバインドされている場所)とCONNECTION_SOCKET(クライアントが接続されている場所)の両方でIPアドレスを取得できるようにする必要があります。Cソケットプログラミング:IPアドレス(IPv6またはIPv4)サーバーの境界を取得し、クライアントを接続しますか?
result_t print_socket_address(int sockfd, socket_type_t socket_type) {
char *ip_address; // address (passive) socket was binded to
int port; // port (passive) socket was binded to
switch(socket_type)
{
case PASSIVE_SOCKET:
if(get_current_address_and_port(sockfd, &ip_address, &port) == FAILURE) {
fprintf(stderr, "get_current_address_and_port: faild!\n");
free(ip_address);
return FAILURE;
}
printf("Created passive socket %d binded to %s:%d\n", sockfd, ip_address, port);
break;
case CONNECTION_SOCKET:
if(get_peer_address_and_port(sockfd, &ip_address, &port) == FAILURE) {
fprintf(stderr, "get_peer_address_and_port: faild!\n");
free(ip_address);
return FAILURE;
}
printf("Socket %d connected to %s:%d\n", sockfd, ip_address, port);
break;
default:
fprintf(stderr, "Incorrect socket type!\n");
free(ip_address);
return FAILURE;
}
free(ip_address);
return SUCCESS;
}
/**
* function retrieves current ip address and port
* socket is bound to for given socket file descriptor
*/
result_t get_current_address_and_port(int sockfd, char **ip_address, int *port) {
struct sockaddr sockaddr;
socklen_t sockaddrlen = sizeof(sockaddr);
if(getsockname(sockfd, &sockaddr, &sockaddrlen) < 0) {
fprintf(stderr, "getsockname: %s\n", strerror(errno));
return FAILURE;
}
sockaddr.sa_family = AF_INET6;
return get_address_and_port_from_sockaddr(&sockaddr, ip_address, port);
}
/**
* function retrieves peer ip address and port
* socket is connected to for given socket file descriptor
*/
result_t get_peer_address_and_port(int sockfd, char **ip_address, int *port) {
struct sockaddr sockaddr;
socklen_t sockaddrlen = sizeof(sockaddr);
if(getpeername(sockfd, &sockaddr, &sockaddrlen) < 0) {
fprintf(stderr, "getpeername: %s\n", strerror(errno));
return FAILURE;
}
return get_address_and_port_from_sockaddr(&sockaddr, ip_address, port);
}
/**
* function unwrap ip address and port from addrinfo structure
*/
result_t get_address_and_port_from_addrinfo(const struct addrinfo *addrinfo, char **ip_address, int *port) {
return get_address_and_port_from_sockaddr((struct sockaddr *)addrinfo->ai_addr, ip_address, port);
}
/**
* function unwrap ip address and port from sockaddr structure
*/
result_t get_address_and_port_from_sockaddr(const struct sockaddr *sockaddr, char **ip_address, int *port) {
*ip_address = (char *) malloc(INET6_ADDRSTRLEN * sizeof(char));
// converting network address to presentation address
if(inet_ntop(sockaddr->sa_family, get_in_addr(sockaddr), *ip_address, INET6_ADDRSTRLEN * sizeof(char)) == NULL) {
fprintf(stderr, "inet_ntop: %s\n", strerror(errno));
return FAILURE;
}
// converting network port to host port
*port = ntohs(get_in_port(sockaddr));
return SUCCESS;
}
/**
* function unwrap in_addr or in6_addr structure from
* sockaddr structure depending on address family
* AF_INET or AF_INET6
*/
void *get_in_addr(const struct sockaddr *sa) {
if(sa->sa_family == AF_INET) // IPv4 address
return &(((struct sockaddr_in*)sa)->sin_addr);
// else IPv6 address
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
/**
* function unwrap in_port from sockaddr structure
* depending on address family AF_INET or AF_INET6
*/
in_port_t get_in_port(const struct sockaddr *sa)
{
if(sa->sa_family == AF_INET) // IPv4 address
return (((struct sockaddr_in*)sa)->sin_port);
// else IPv6 address
return (((struct sockaddr_in6*)sa)->sin6_port);
}
しかし、このコードを使用すると、私は奇妙な動作をします。 431C:F9:へ:: ba54バインドさパッシブソケット4に作成
:55401
55401はポート番号で、それは正しいです私のサーバーの境界ソケットは、例えば、あるIPアドレスが返されます。しかし、これは何ですか:: ba54:431c:f9?おそらく、これはIPv6だと思います。しかし、なぜ?ローカルエリアネットワークのマイコンピュータにIPアドレス192.168.8.102があります! クライアントプログラムでこのサーバーに接続しようとすると、192.168.8.102のIPアドレスを使用しなければなりません。ba54:431c:f9「ルートが見つかりません」というエラーが表示されますか?クライアントがサーバと192.168.8.102のIPアドレスを使用して接続し、接続したコンピュータのIPアドレスとポート番号を出力すると、次のような別のODD IPアドレスが得られます。
ソケット3 :: 3300 :5208:6d16:9c88:55401
ここでポート番号が一致し、IPアドレスが正しくありません。 クライアントソケットは、サーバと接続する前にローカルにバインドしている間に、接続しているコンピュータのIPアドレスと同じIPアドレスにバインドされています(実際にはLANネットワーク内のコンピュータとは物理的に異なります):: 3300:5208:6d16:9c88: 52040ここで、52040はクライアントがソケットをバインドしたポートです。
私は、サーバコンピュータ192.168.8.1のIPアドレスをIPv6に変換しようとしましたが、クライアントで使用された場合、0:0:0:0:0:ffff:c0a8:866のようなものがあります。サーバーに接続するプログラムが正しく動作します! :: 3300:5208:6d16:9c88:しかし、上記の関数を使用してクライアントのような、この全く異なるIPアドレスを印刷52040
を、どのように私は、この関数を記述する必要があります
サーバーの印刷IPアドレスを有効にし、 (一般にIPv6またはIPv4は任意のアドレス/任意のポートに接続できます)
クライアントは、バインドされているIPアドレスとポート番号を印刷して接続できます必要に応じてIPv4またはIPv6を使用します)。
クライアントプログラムで使用できるサーバープログラムのIPアドレスとポート番号に両方を接続したいと考えています。ネットワークの設定で見つかったコンピュータのアドレスで、ポート番号が正しいと仮定して接続しようとする必要があります。
あなたは、このコードを達成しようとしているもの: 'sockaddr.sa_family = AF_INET6;'?あなたはあなたがあなたが戻って予期せぬIPv6アドレスを説明するかもしれないIPv6に得たアドレスの家族を変更するように私のように見えます。 –