很久以前参考了https://www.genivia.com/doc/soapdoc2.html 中的一段:

How to Create a Multi-Threaded Stand-Alone Service

完成了一个简单多线程服务器的编写。

但是一直以来服务器运行一段时间,接收一定量的请求后,就会出现服务器再也不返回的情况。

怀疑过是不是socket数量不够用了,后来跟踪发现还能正常listen。

怀疑是不是工作线程异常退出了,补充了所需的日志,也没有。

后来查询到,有人曾经也问过这个问题:https://sourceforge.net/p/gsoap2/bugs/844/

在gsoap的代码中加入日志,确实是在soap_serve卡住了,而卡住的位置就是在recv函数,位于文件stdsoap2.cpp的933行(72行):

 frecv(struct soap *soap, char *s, size_t n)
{ register int r;
register int retries = ; /* max 100 retries with non-blocking sockets */
soap->errnum = ;
#if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
if (soap->is)
{ if (soap->is->good())
return soap->is->read(s, (std::streamsize)n).gcount();
return ;
}
#endif
if (soap_valid_socket(soap->socket))
{ for (;;)
{
#ifdef WITH_OPENSSL
register int err = ;
#endif
#ifdef WITH_OPENSSL
if (soap->recv_timeout && !soap->ssl) /* SSL: sockets are nonblocking */
#else
if (soap->recv_timeout)
#endif
{ for (;;)
{ r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout);
if (r > )
break;
if (!r)
return ;
r = soap->errnum;
if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
return ;
}
}
#ifdef WITH_OPENSSL
if (soap->ssl)
{ r = SSL_read(soap->ssl, s, (int)n);
if (r > )
return (size_t)r;
err = SSL_get_error(soap->ssl, r);
if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
return ;
}
else if (soap->bio)
{ r = BIO_read(soap->bio, s, (int)n);
if (r > )
return (size_t)r;
return ;
}
else
#endif
#ifdef WITH_GNUTLS
if (soap->session)
{ r = (int)gnutls_record_recv(soap->session, s, n);
if (r >= )
return (size_t)r;
}
else
#endif
{
#ifndef WITH_LEAN
if ((soap->omode & SOAP_IO_UDP))
{ SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer);
memset((void*)&soap->peer, , sizeof(soap->peer));
r = recvfrom(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
soap->peerlen = (size_t)k;
#ifndef WITH_IPV6
soap->ip = ntohl(soap->peer.sin_addr.s_addr);
#endif
}
else
#endif
r = recv(soap->socket, s, (int)n, soap->socket_flags);
#ifdef PALM
/* CycleSyncDisplay(curStatusMsg); */
#endif
if (r >= )
return (size_t)r;
r = soap_socket_errno(soap->socket);
if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
{ soap->errnum = r;
return ;
}
}
#if defined(WITH_OPENSSL)
if (soap->ssl && err == SSL_ERROR_WANT_WRITE)
r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : );
else
#elif defined(WITH_GNUTLS)
if (soap->session && gnutls_record_get_direction(soap->session))
r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : );
else
#endif
r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : );
if (!r && soap->recv_timeout)
return ;
if (r < )
{ r = soap->errnum;
if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
return ;
}
if (retries-- <= )
return ;
#ifdef PALM
r = soap_socket_errno(soap->socket);
if (r != SOAP_EINTR && retries-- <= )
{ soap->errnum = r;
return ;
}
#endif
}
}
#ifdef WITH_FASTCGI
return fread(s, , n, stdin);
#else
#ifdef UNDER_CE
return fread(s, , n, soap->recvfd);
#else
#ifdef WMW_RPM_IO
if (soap->rpmreqid)
r = httpBlockRead(soap->rpmreqid, s, n);
else
#endif
#ifdef WIN32
r = _read(soap->recvfd, s, (unsigned int)n);
#else
r = read(soap->recvfd, s, (unsigned int)n);
#endif
if (r >= )
return (size_t)r;
soap->errnum = soap_errno;
return ;
#endif
#endif
}

按照上面的网址链接,解决此问题的办法是:

You have to set the recv_timeout and send_timeout values as well. I/O may block otherwise

更神奇的是在这个文档中:https://www.genivia.com/tutorials.html

例子里面的soap则添加了超时处理!

int main()
{
struct soap *soap = soap_new1(SOAP_IO_KEEPALIVE); /* new context with HTTP keep-alive enabled */
SOAP_SOCKET m; /* master socket */
THREAD_TYPE tids[POOLSIZE]; /* thread pool */
int i;
soap->accept_timeout = **; /* quit after 24h of inactivity (optional) */
soap->send_timeout = soap->recv_timeout = ; /* 5 sec socket idle timeout */
soap->transfer_timeout = ; /* 10 sec message transfer timeout */

转自:https://blog.csdn.net/wayright/article/details/80608123

很久以前参考了https://www.genivia.com/doc/soapdoc2.html 中的一段:
How to Create a Multi-Threaded Stand-Alone Service

完成了一个简单多线程服务器的编写。

但是一直以来服务器运行一段时间,接收一定量的请求后,就会出现服务器再也不返回的情况。

怀疑过是不是socket数量不够用了,后来跟踪发现还能正常listen。

怀疑是不是工作线程异常退出了,补充了所需的日志,也没有。

后来查询到,有人曾经也问过这个问题:

https://sourceforge.net/p/gsoap2/bugs/844/

在gsoap的代码中加入日志,确实是在soap_serve卡住了,而卡住的位置就是在recv函数,位于文件stdsoap2.cpp的933行(72行):

frecv(struct soap *soap, char *s, size_t n)
{ register int r;
register int retries = ; /* max 100 retries with non-blocking sockets */
soap->errnum = ;
#if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
if (soap->is)
{ if (soap->is->good())
return soap->is->read(s, (std::streamsize)n).gcount();
return ;
}
#endif
if (soap_valid_socket(soap->socket))
{ for (;;)
{
#ifdef WITH_OPENSSL
register int err = ;
#endif
#ifdef WITH_OPENSSL
if (soap->recv_timeout && !soap->ssl) /* SSL: sockets are nonblocking */
#else
if (soap->recv_timeout)
#endif
{ for (;;)
{ r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout);
if (r > )
break;
if (!r)
return ;
r = soap->errnum;
if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
return ;
}
}
#ifdef WITH_OPENSSL
if (soap->ssl)
{ r = SSL_read(soap->ssl, s, (int)n);
if (r > )
return (size_t)r;
err = SSL_get_error(soap->ssl, r);
if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
return ;
}
else if (soap->bio)
{ r = BIO_read(soap->bio, s, (int)n);
if (r > )
return (size_t)r;
return ;
}
else
#endif
#ifdef WITH_GNUTLS
if (soap->session)
{ r = (int)gnutls_record_recv(soap->session, s, n);
if (r >= )
return (size_t)r;
}
else
#endif
{
#ifndef WITH_LEAN
if ((soap->omode & SOAP_IO_UDP))
{ SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer);
memset((void*)&soap->peer, , sizeof(soap->peer));
r = recvfrom(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
soap->peerlen = (size_t)k;
#ifndef WITH_IPV6
soap->ip = ntohl(soap->peer.sin_addr.s_addr);
#endif
}
else
#endif
r = recv(soap->socket, s, (int)n, soap->socket_flags);
#ifdef PALM
/* CycleSyncDisplay(curStatusMsg); */
#endif
if (r >= )
return (size_t)r;
r = soap_socket_errno(soap->socket);
if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
{ soap->errnum = r;
return ;
}
}
#if defined(WITH_OPENSSL)
if (soap->ssl && err == SSL_ERROR_WANT_WRITE)
r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : );
else
#elif defined(WITH_GNUTLS)
if (soap->session && gnutls_record_get_direction(soap->session))
r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : );
else
#endif
r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : );
if (!r && soap->recv_timeout)
return ;
if (r < )
{ r = soap->errnum;
if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
return ;
}
if (retries-- <= )
return ;
#ifdef PALM
r = soap_socket_errno(soap->socket);
if (r != SOAP_EINTR && retries-- <= )
{ soap->errnum = r;
return ;
}
#endif
}
}
#ifdef WITH_FASTCGI
return fread(s, , n, stdin);
#else
#ifdef UNDER_CE
return fread(s, , n, soap->recvfd);
#else
#ifdef WMW_RPM_IO
if (soap->rpmreqid)
r = httpBlockRead(soap->rpmreqid, s, n);
else
#endif
#ifdef WIN32
r = _read(soap->recvfd, s, (unsigned int)n);
#else
r = read(soap->recvfd, s, (unsigned int)n);
#endif
if (r >= )
return (size_t)r;
soap->errnum = soap_errno;
return ;
#endif
#endif
}

按照上面的网址链接,解决此问题的办法是:

You have to set the recv_timeout and send_timeout values as well. I/O may block otherwise

更神奇的是在这个文档中:https://www.genivia.com/tutorials.html

例子里面的soap则添加了超时处理!

int main()
{
struct soap *soap = soap_new1(SOAP_IO_KEEPALIVE); /* new context with HTTP keep-alive enabled */
SOAP_SOCKET m; /* master socket */
THREAD_TYPE tids[POOLSIZE]; /* thread pool */
int i;
soap->accept_timeout = **; /* quit after 24h of inactivity (optional) */
soap->send_timeout = soap->recv_timeout = ; /* 5 sec socket idle timeout */
soap->transfer_timeout = ; /* 10 sec message transfer timeout */

转自:https://blog.csdn.net/wayright/article/details/80608123

GSOAP服务卡住?的更多相关文章

  1. gsoap使用总结

    WebService.soap.gsoap基本概念 WebService服务基本概念:就是一个应用程序,它向外界暴露出一个可以通过web进行调用的API,是分布式的服务组件.本质上就是要以标准的形式实 ...

  2. gsoap

    C++中如何使用gsoap开发WebService 1. 什么是gSOAPgSOAP是一个夸平台的,用于开发Web Service服务端和客户端的工具,在Windows.Linux.MAC OS和UN ...

  3. gsoap开发webservice

    gSOAP编译工具提供了一个SOAP/XML 关于C/C++ 语言的实现,从而让C/C++语言开发web服务或客户端程序的工作变得轻松了很多.绝大多数的C++web服务工具包提供一组API函数类库来处 ...

  4. 踩坑踩坑之Flask+ uWSGI + Tensorflow的Web服务部署

    一.简介 作为算法开发人员,在算法模块完成后,拟部署Web服务以对外提供服务,从而将算法模型落地应用.本文针对首次基于Flask + uWSGI + Tensorflow + Nginx部署Web服务 ...

  5. (BUG记录)记一次与其他系统交互协作时造成的锁表问题

    最近两日做公司电信某计费项目时,接收一个银行对账的任务,在完成对账后.电信和银行两方金额一致时需要进行充值.冲正操作保持金额一致.冲正服务是JAVA统一调用Tuxedo服务,这个服务已经是一个稳定可用 ...

  6. 使用GSoap开发WebService客户端与服务端

    Gsoap 编译工具提供了一个SOAP/XML 关于C/C++ 语言的实现, 从而让C/C++语言开发web服务或客户端程序的工作变得轻松了很多. 用gsoap开发web service的大致思路 我 ...

  7. gsoap创建webservice服务简单教程

    版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] WebServicesoapgsoap 使用gsoap创建webservice服务 下载gsop 准备待导出的服务接口定义文件比 ...

  8. Linux下用gSOAP开发Web Service服务端和客户端程序

    网上本有一篇流传甚广的C版本的,我参考来实现,发现有不少问题,现在根据自己的开发经验将其修改,使用无误:另外,补充同样功能的C++版本,我想这个应该更有用,因为能用C++,当然好过受限于C. 1.gS ...

  9. C#访问gsoap的服务--可用

    问题来源: C++开发一个webservice,然后C#开发客户端,这样就需要C#的客户端访问gsoap的服务端.(大家都知道gsoap是C/C++开发webservice的最佳利器) 为什么不考虑直 ...

随机推荐

  1. arcgis api for javascript 学习(四) 地图的基本操作

    1.文章讲解的为地图的平移.放大.缩小.前视图.后视图以及全景视图的基本功能操作 2.主要用到的是arcgis api for javascript中Navigation的用法,代码如下: <! ...

  2. [b0022] python 归纳 (八)_多进程_基本使用

    # -*- coding: UTF-8 -*- """ 测试进程使用 multiprocessing.Process 使用: 1. 准备一个函数<fun>,子 ...

  3. docker网络之(三)

    docker4种网络 基于docker run创建容器时,可以使用--net选项指定容器的网络模式:Docker默认有以下4种网络模式: host模式,使用--net=host指定 container ...

  4. Maven配置以及环境搭配

    1. Maven简单介绍 Apache Maven是个项目管理和自动构建工具,基于项目对象模型(POM)的概念. 作用:完成项目的相关操作,如:编译,构建,单元测试,安装,网站生成和基于Maven部署 ...

  5. 6.2 DataFrame

    一.DataFrame概述 在Spark SQL中,DataFrame就是它的数据抽象,对DataFrame进行转换操作. DataFrame的推出,让Spark具备了处理大规模结构化数据的能力,不仅 ...

  6. 运行java程序

    使用方式: java类名 硬盘上有HelloWorld.class,那么类名就是HelloWorld java HelloWorld[运行先到class路径下] 一定要注意:java命令后面跟的不是文 ...

  7. TeamyinyinFish->鱼嘤嘤小分队软件工程beta迭代作业

    Github项目的链接 github工作组链接 github后台部分项目代码,issue提交在这个项目 github小程序前端部分项目代码链接 scrum会议时间 链接 第十一周 十一周博客 第十二周 ...

  8. 剑指Offer-8.跳台阶(C++/Java)

    题目: 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). 分析: 实际上就是斐波那契数列的一个应用,青蛙跳上n级台阶的跳法数等于跳 ...

  9. CF798D Mike and distribution

    CF798D Mike and distribution 洛谷评测传送门 题目描述 Mike has always been thinking about the harshness of socia ...

  10. 2019 SDN阅读作业(2)

    1.过去20年中可编程网络的发展可以分为几个阶段?每个阶段的贡献是什么? 可编程网络的发展可以分为以下三个阶段: (1)主动网络(Active networking,20世纪90年代中期到21世纪初) ...