我有一个同时充当客户端和服务器的应用程序。作为服务器,它接受端口xxxxAgent URL上的SOAP请求,并在端口上向发送方发送通知。
因此,基本上它在端口xxxx上充当服务器,在端口yyyy上充当客户端。我的服务有一个专用的IP ( IPv6或IPv4 )。
我们使用GSOAP进行通信,并为客户端绑定使用重写GSOAP函数tcp_connect()。
目前,我正面临服务向IPv6过渡的问题。用例:当我监听IPv6地址而我的通知URL是IPv4.
在GSOAP实现中,从Notification创建了一个套接字。
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的类型),如果套接字类型不匹配,绑定就会失败。
当套接字家族和代理ip地址属于不同的家庭时,如何使我的客户端绑定工作?
发布于 2014-06-17 11:41:32
也许我没有得到您正在尝试的东西,或者您对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中的某个功能,应该停止这样做,要么是如果您绝对需要一个后台通道,就不会调用客户端套接字上的绑定。
https://stackoverflow.com/questions/24262123
复制相似问题