bind failed in soap_bind() 问题解决

使用gsoap协议的时候,如果服务异常退出,再次打开服务的时候,就会出现“bind failed in soap_bind()”的错误,如下:
[billing_dx@bmcs1 test]$addserver 9999
SOAP 1.1 fault: SOAP-ENV:Server [no subcode]
"Address already in use"
Detail: bind failed in soap_bind()



想让这个异常重现的方法很简单,启动服务端之后,再启动客户端,一旦客户端和服务端进行交互之后,立马使用“Ctrl+C”强制退出服务,然后立马重新服务,就会问题重现。


虽然等一段时间就可以重新使用该端口,但是,有没有办法避免这种情况呢?
使用sock的时候,我们其实也会遇到同样的问题,就是服务端异常退出的时候,就会出现“bind: Address already in use”的错误。而解决办法就是使用“setsockopt”函数,使用方式如下:
int optval=1;
if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval))<0)
{
	perror("Failed to set address reuse.\n");
	exit(1);
}
if((bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr)))==-1)
{
	perror("bind");
	exit(1);
}


这是在bind函数之前,这样的话,即使服务器端异常退出,也不会出现绑定错误的提示了。
后来上网搜了一下setsockopt的用法,发现他是用来设置socket的状态,当然,它的使用方法很多。对于上面的用法,我说一下我自己的理解:
当我们在关闭socket的时候,socket一般不会立即关闭,而是经历了一个TIME_WAIT的过程,我们在异常退出socket的时候,也是如此。因此,如果我们异常退出之后再重新使用socket话,就会因为上面的时间延迟导致端口已经被绑定。而这个函数的作用,就是让socket不再延时,而是直接退出,这样我们就可以使用原来的socket而不会发生bind错误了。


在gsoap中,我们通过修改gsoap提供的“stdsoap2.c”文件,就可以达到目的。
通过搜索出现的错误信息“bind failed in soap_bind()”,找到了对应的文件是“stdsoap2.c”,对应的文件内容如下:
if (bind(soap->master, (struct sockaddr*)&soap->peer, (int)soap->peerlen))
{
    soap->errnum = soap_socket_errno(soap->master);
    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
    soap_closesock(soap);
    soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
    return SOAP_INVALID_SOCKET;
}



在这之前,添加“setsockopt”函数,使用同样的异常处理就可以了,如下:
int optval=1;
if (setsockopt(soap->master,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)) < 0)
{
    soap->errnum = soap_socket_errno(soap->master);
    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
    soap_closesock(soap);
    soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
    return SOAP_INVALID_SOCKET;
}
if (bind(soap->master, (struct sockaddr*)&soap->peer, (int)soap->peerlen))
{
    soap->errnum = soap_socket_errno(soap->master);
    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
    soap_closesock(soap);
    soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
    return SOAP_INVALID_SOCKET;
}



进行同样的服务端异常退出再登陆,OK,不会出现端口号绑定的情况了。


扩展阅读: http://blog.csdn.net/olei_oleitao/article/details/9849633 

你可能感兴趣的:(gsoap)