- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我写了如下代码。此代码应该能够检索 PASSIVE_SOCKET(服务器绑定(bind)其套接字的位置)和 CONNECTION_SOCKET(客户端已连接的位置)的 IP 地址。
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);
}
但是当我使用这段代码时,我得到了一些奇怪的行为。返回的我的服务器绑定(bind)套接字的 IP 地址例如:
Created passive socket 4 binded to ::ba54:431c:f9:55401
55401是端口号,它是正确的。但这是什么::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 地址,如下所示:
Socket 3 connected to ::3300:5208:6d16:9c88:55401
所以这里只有端口号匹配,IP地址不正确!更多关于客户端套接字在与服务器连接之前在本地绑定(bind)时绑定(bind)的 IP 地址与其所连接的计算机的 IP 地址相同(它是我的 LAN 网络中物理上不同的计算机),即::3300:5208:6d16:9c88:52040 ,其中 52040 是客户端绑定(bind)其套接字的端口。
我什至尝试将服务器计算机 192.168.8.1 的 IP 地址转换为 IPv6,但我得到的是这样的结果: 0:0:0:0:0:ffff:c0a8:866 以及在客户端程序中使用时的地址连接到服务器工作正常!但是使用上述函数的客户端打印出这个完全不同的IP地址,例如:::3300:5208:6d16:9c88:52040
那么我应该如何编写这个函数:
启用服务器打印其绑定(bind)的IP地址和端口号(一般来说IPv6或IPv4可以连接到它选择的任何地址/任何端口)
使客户端能够打印其绑定(bind)和连接的IP地址和端口号(通常可以根据需要使用IPv4或IPv6)。
我想在服务器程序中显示IP地址和端口号,然后我可以在客户端程序中使用它们来连接两者。现在我需要猜测它应该是在网络偏好设置中找到的我的计算机地址,并假设端口号是正确的,然后尝试连接。
最佳答案
从 get_current_address_and_port
中删除此行。
sockaddr.sa_family = AF_INET6;
我不知道该行是如何写入您的代码中的,但它是不正确的。
通过删除该行,将解决 IPv4 的大部分问题。
您的代码被硬连线为使用struct sockaddr
。 IIRC,无论如何,sockaddr 对于 IPv6 地址来说都不够大。我可以建议将其转换为 sockaddr_storage
以便初始调用 getsockname
和 getpeername
以便您的代码可以更好地支持 IPv4 和 IPv6。
修复示例:
result_t get_current_address_and_port(int sockfd, char **ip_address, int *port) {
struct sockaddr_storage address = {0};
socklen_t sockaddrlen = sizeof(address);
if(getsockname(sockfd, (struct sockaddr*)(&address), &sockaddrlen) < 0) {
fprintf(stderr, "getsockname: %s\n", strerror(errno));
return FAILURE;
}
return get_address_and_port_from_sockaddr((struct sockaddr*)(&address), ip_address, port);
}
result_t get_peer_address_and_port(int sockfd, char **ip_address, int *port) {
struct sockaddr_storage address = {0};
socklen_t sockaddrlen = sizeof(address);
if(getpeername(sockfd, (struct sockaddr*)(&address), &sockaddrlen) < 0) {
fprintf(stderr, "getpeername: %s\n", strerror(errno));
return FAILURE;
}
return get_address_and_port_from_sockaddr((struct sockaddr*)(&address), ip_address, port);
}
关于C套接字编程: get IP address (IPv6 or IPv4) server bounds to, 与客户端连接到?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44098511/
目前部署在 Kubernetes 中的服务,通过 Calico BGP 将 Service 与集群外网络打通,并在外部的 nginx 中配置 Service 地址对外进行服务暴露。经过一段时间的观察
如发现here , 有一种新的 kube 服务是 IPVS 并且有很多负载均衡算法。 唯一的问题是我没有找到指定这些算法的位置。 我的理解: rr:循环法->循环调用后端pod lc:最少连接-> 将
我想尝试这种新的代理模式以及它为我们的一些应用程序提供的各种调度程序。到目前为止,我一直无法找到更改默认模式的方法 iptables至 ipvs在 GKE 节点上。 每个人都说通过--proxy-mo
我想在现有集群中为 IPVS 启用 Kube-proxy 模式。目前,它在 IPtables 上运行。如何在不影响现有工作负载的情况下将其更改为 IPVS? 我已经安装了所有必需的模块来启用它。另外,
我正在开发的应用程序作为 Kubernetes 集群中的部署运行。为此部署创建的 Pod 分布在集群中的各个节点上。我们的应用程序一次只能处理一个 TCP 连接,并且会拒绝进一步的连接。目前,我们使用
我是一名优秀的程序员,十分优秀!