IPv4和IPv6之间的混合模式通信

时间:2014-06-17 11:02:48

标签: c++ sockets ipv6 gsoap

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

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

我们正在使用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;
    }

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

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

1 个答案:

答案 0 :(得分:2)

也许我没有得到你正在尝试的东西,或者你对TCP / IP和RPC通常如何工作有一些误解。

让我解释你的设置,然后展示我认为奇怪的事情。

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

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

但是错过了设置这一点,至少说ODD。虽然我从未使用过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