【问题标题】:Mix mode communication between IPv4 and IPv6IPv4 和 IPv6 之间的混合模式通信
【发布时间】:2014-08-07 08:47:15
【问题描述】:

我有一个作为客户端和服务器的应用程序。作为服务器,它在端口 xxxx[代理 URL] 上接受 SOAP 请求,并在端口 yyyy [通知 URL] 上向发送者发送通知。

所以基本上它在端口 xxxx 上充当服务器,在端口 yyyy 上充当客户端。我的服务有一个 IPv6 或 IPv4 的专用 IP。

我们使用 GSOAP 进行通信并覆盖 GSOAP 函数 tcp_connect() 进行客户端绑定。

目前,我面临着将服务过渡到 IPv6 的问题。用例:当我监听 IPv6 地址并且我的通知 URL 是 IPv4...

从 GSOAP 实现中,从通知 URL 创建一个套接字。

sk = socket(res->ai_family, res->ai_socktype, res->ai_protocol);

现在我们尝试相应地绑定到这个套接字(IPv4 或 IPv6):

    struct addrinfo hints, *res, *p;
    int status;
    const char* client_ip = AGENT_CLIENT_IP;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    if( (status=getaddrinfo(client_ip, NULL, &hints, &res))!=0 )
    {
            sprintf(err_msg_buf,"bind failed in tcp_connect()");
            soap->fclosesocket(soap, sk);
            return error;
    }

    for( p=res; p!=NULL; p=p->ai_next){
        if(p->ai_family == AF_INET) 
        {
            struct sockaddr_in * ipv4 = (struct sockaddr_in *)p->ai_addr;
                    status = bind(sk, ipv4, (int)sizeof(struct sockaddr_in));
        }
        else if(p->ai_family == AF_INET6)
        {
            struct sockaddr_in6 * ipv6 = (struct sockaddr_in6 *)p->ai_addr;
                    status = bind(sk, ipv6, (int)sizeof(struct sockaddr_in6));
        }
        else
        {
                sprintf(err_msg_buf,"tcp_connect() error. IP Address neither IPv6 nor IPv4 ");
                soap->fclosesocket(soap, sk);
                return error;
        }

        break;
    }

            if(-1 == status)
            {
                    sprintf(err_msg_buf," Binding to client host ip failed in tcp_connect()");
                    return error;
    }

由于已经创建了套接字(根据 Notification URL 的类型),如果套接字类型不匹配,则绑定失败。

当套接字系列和代理IP地址属于不同系列时,如何使我的客户端绑定工作?

【问题讨论】:

  • 我知道这不是一个解决方案,但我的第一个想法是“将应用程序拆分为单独的客户端和服务器部分,每个部分都可以独立为 IPv4 或 IPv6,并使用某种 IPC 来链接它们"
  • 看来您必须创建两个单独的套接字。这不可能吗?

标签: c++ sockets ipv6 gsoap


【解决方案1】:

也许我没有得到您正在尝试的内容,或者您​​对 TCP/IP 和 RPC 的正常工作方式有一些误解。

让我解释一下你的设置,然后展示我认为奇怪的地方。

您有一台服务器和一个或多个客户端。服务器接受固定端口上的 IPv4 和 IPV6 连接,比如 1337。要回答请求,您在不同的固定端口上打开一个新的 TCP 流(或者可能是 SOAP),比如 1338。你现在想知道为什么,当一秒钟客户端连接绑定到1338失败?

简短的回答是:“端口正在使用中,呃,我们是不同的端口!”

但这忽略了设置,至少可以说是奇数。虽然我从未使用过 GSOAP,但我使用过 SOAP 和其他 RPC 框架,并且您概述的内容很奇怪,除非我遗漏了您没有概述的内容。

奇怪的第一件事是,如果您需要一个 SOAP 请求的答案,为什么您只是简单地制定一个带有返回值的请求?调用 SOAP 函数,客户端将阻塞,直到得到响应。如果您不希望调用在调用的相对较长时间内阻塞,请异步执行整个操作。

所以您想稍后将数据传回给客户端?这里有两种解决方案,或者客户端轮询服务器,或者打开一个到客户端的新 SOAP 连接。第一个解决方案基本上是可取的,因为在大多数情况下,客户端可以连接到服务器,但反之则不行。例如客户端可以在 NAT 之后,你现在做什么?当您知道客户端始终可以访问时,第二种解决方案效果很好。

在我看来,您正在尝试执行第二个“返回渠道”解决方案。在这种情况下,为什么要绑定到端口?任何 IP 连接的客户端都不需要绑定到端口。操作系统将自动分配一个可用端口。然后,您需要做的是将客户端上的端口绑定到一个众所周知的 IP。然后,您使用这个众所周知的客户端端口并在服务器上的connect 中使用它(或者不使用,因为您使用的是 SOAP)。

由于这一切都令人困惑,让我用一个小图来说明这一点:

                   Client                   Server
                   ------                   ------
Request Channel    <random port>            1337
Back Channel       1338                     <random port>

总结一下:

所以要么您是重新实现在 SOAP 中有效的东西并且应该停止这样做,或者如果您绝对需要反向通道,不要在客户端套接字上调用 bind.

【讨论】:

  • 第三种解决方案是让客户端长轮询进度。
  • @Calvin 确实如此。虽然我没有提到轮询间隔或持续时间,但值得一提。
  • 但是这些对我来说是不可能的情况,架构是固定的,并且在仅使用 IPv4 或 IPv6 时可以正常工作。不过谢谢
  • 但是我还是不明白为什么你bind服务器上的传出套接字。这可能是拼图中缺失的部分吗?
猜你喜欢
  • 2020-08-27
  • 1970-01-01
  • 1970-01-01
  • 2020-12-20
  • 1970-01-01
  • 2019-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多