IPv4和IPv6之间的Mix模式通信



我有一个既充当客户端又充当服务器的应用程序。作为服务器,它在端口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;
    }

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

如何使我的客户端绑定工作当套接字族和代理ip地址是不同的族

也许我没有得到你正在尝试的东西,或者你对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

最新更新