电脑客户端都是c语言写的吗,c语言直接写soap客户端

原理大家都知道,直接看代码:

(注明:在其他网站可能会看到同样内容的文章,不是抄袭,都是本人之作。只不过看那个网站不顺眼,把文章移到这上面来了)

对于一个C程序员来说,写webservice是件比较头痛的事。好在MS下有相应的Toolkit,在VC2003开始,编译环境已经集成了相关功能,

点"Project->Add Web Reference",显示一个对话框,把一.个wsdl的地址写上,会自动分析生成相关的C++的 class,然后就可以用了。

开源软件,有个很不错的产品叫gSoap,使用起来应该更简单,google上能找出很多文章来介绍。这个产品是多平台的,最简单的使用方法就是下

载其二进制文件,一共有两个,wsdl2h 和soapcpp2,看名字就知道了, 前者把wsdl转成.h,后者再根据这个.h生成相关的class

或函数。用的时候,把生成的几个.h,.c放在自己的工程目录下,再到gSoap源码中找出stdsoap2.h和stdsoap2.cpp,都放进工

程,不用引入任何lib或dll,直接使用就可以了。stdsoap2.cpp这里面已经实现了socket的通信功能。

MS自己的soap功能已经淘汰一些不太安全的方式,所以有些webservice解析出错,比如最近用到的一个关于rpc的,MS不支持。gSoap兼容性相对好一些, 可以用。

而且,gSoap最大的好处,就是可以跟踪调试源码,比如提交时的HTTP字符串内容,接收到的HTTP字符串,直接可以显示出来,省的再用抓包工具了。在调试方面来讲,gSoap远远超过了MS,想想对com进行调试,没几年的经验是弄不好的。

gSoap在Linux下工作也很不错,使用方法和Windwos下完全一样,先把wsdl解析出来,然后直接使用.h和.c。

最近调试一个webservice,检查的非常苛刻,比如HTTP里的Content-Length,一般写为0就可以了,然后会检查\r\n\r

\n,表示结束。但这个服务器端非要知道Content-Length的数值,然后再检查结束符,如果这里写0,直接返回错误。调试了一下gSoap,发

现如果不特意指定的话,Content-Length总是置为0。不过这个问题相对也很好解决,只是在调试代码中,很快就了解了soap底层的一些实现过

程,然后自己用socket仿照也实现了一个简单的。

代码演示如下:

//*****************

//file: main.c

//*****************

#include #pragma comment(lib, "ws2_32.lib")

int m_hSocket;

int Connect( const char* szHostAddr, int nPort )

{

SOCKADDR_IN sockAddr;

memset(&sockAddr,0,sizeof(sockAddr));

sockAddr.sin_family = AF_INET;

sockAddr.sin_addr.s_addr = inet_addr(szHostAddr);

if (INADDR_NONE == sockAddr.sin_addr.s_addr)

{

LPHOSTENT lphost;

lphost = gethostbyname(szHostAddr);

if (lphost != NULL)

sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;

else

{

WSASetLastError(WSAEINVAL);

return FALSE;

}

}

sockAddr.sin_port = htons((u_short)nPort);

if (SOCKET_ERROR == connect(m_hSocket, (LPSOCKADDR)&sockAddr, sizeof(sockAddr)))

{

//int nError = WSAGetLastError();

return -1;

}

return 0;

}

//length应该足够大,timeout单位是秒

int TcpRecvTimeout(int fd, char* buffer, int length, int timeout)

{

struct timeval TimeOut;

int recv_lenth = 0;

//int left_length = length;

int fd_max=fd+1;

int sel_ret=0, recv_ret=0;

fd_set fdset ;

TimeOut.tv_sec = timeout;

TimeOut.tv_usec = 0;

FD_ZERO(&fdset);

FD_SET(fd, &fdset);

sel_ret = select(fd_max, &fdset, NULL, NULL, &TimeOut);

if (sel_ret > 0)

{

while (1)

{

//while (sel_ret==-1 && errno == EINTR);

recv_ret = recv(fd, buffer, length, 0/*MSG_NOSIGNAL*/);

if (recv_ret > 0)

{

recv_lenth += recv_ret;

//left_length -= recv_ret;

buffer += recv_ret;

}

else if (recv_ret == 0)//socket close

{

return recv_lenth;

}

else if (recv_ret < 0)//SOCKET_ERROR

{

return recv_lenth;

}

}

}

else if (sel_ret < 0)

{

return -1;

}

else//sel_ret == 0

{

//超时

return 0;

}

return recv_lenth;

}

int TcpSend(int fd, char* buffer, int length)

{

int left_length = length;

int send_ret = 0;

while (left_length>0)

{

send_ret = send(fd, buffer, left_length, 0);

if (send_ret < 0)

{

return -1;

}

if (send_ret < left_length)

{

left_length -= send_ret;

buffer += send_ret;

}

else

{

left_length = 0;

break;

}

if ((left_sec -= 2) <= 0)

{

break;

}

}

return (left_length<0) ? length : length-left_length;

}

// 发送字符串,最关键的是组HTTP头,如果这里组不好,服务器响应就有问题

int send_xml()

{

char* pSend;//要发送的内容,应该是一组xml字符串

_snprintf(tmp, 4096,

"POST /monitorService/services/ConfigServiceSOAP HTTP/1.1\r\n"

"Content-Type: text/xml\r\n"

"User-Agent: XML Spy\r\n"

"SOAPAction: \""

"Host: 127.0.0.1:8081\r\n"

"Content-Length: %d\r\n"

"\r\n"

"\r\n"

%s,

strlen(pSend),pSend);

//组包结束,开始发送

return TcpSendTimeout(m_hSocket,tmp, leng);

}

int main()

{

int nRet = 0;

char buff[2048];

WSADATA wsaData;

WSAStartup(MAKEWORD(2,2),&wsaData);

if ((m_hSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1)

{

perror("创建套接字失败");

exit(errno);

}

else

{

printf("创建套接字成功\n");

}

nRet = Connect("127.0.0.1", 8081);

if (nRet != 0)

{

exit(errno);

}

send_xml();//这里发送字符串

nRet = TcpRecvTimeout(m_hSocket, buff, 2048, 5);

close(m_hSocket);

if (nRet > 0)

{

//收到webservice值,开始解析,接收的内容先是HTTP信息头,然后跟着是xml格式的字符串

}

WSACleanup();

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值