vc 与webservice通信有这么几种方法,现在总结一下。
首先webservice服务会提供接口,接口的说明都会放在一个wsdl文档中。没有接触过vc与webservice通信的开发人员拿到这个接口说明文档时可能无从下手, 下面说第一种方法。
1. 利用sproxy.exe 生成一个代理类。
vc的安装目录下,在bin目录下会有sproxy.exe 这样一个工具(vs2008下没有,需要下载源码编译成sproxy.exe放到bin目录下),然后在dos下,执行如下命令sproxy.exe /wsdl /namespace:xxx yyy.wsdl /out:zzz.h。yyy.wsdl 是webservice的接口描述文档,zzz.h是生成的头文件,在zzz.h中,有soap消息包封装的定义等等,我们需要的就是这个头文件。在我们的工程中包含这个头文件zzz.h,
在这个头文件中,有命名空间的定义也就是namespace:xxx.
工程中需要using namespace xxx;
模板定义 typedef CFuncT<> Func; //头文件中包含这个模板定义,直接拷贝过来加入到工程。
调用接口前需要初始化com组件。
如下方式
#include “zzz.h”
using namespace xxx;
typedef CFuncT<> Func;
CoInitialize(NULL);
xxx::CFunc ws;
ws.SetUrl(strAddress);
HRESULT hr = ws.Func(temp, &str); //Func 为wsdl中描述的接口
CoUninitialize();2. 使用com组件自己封装soap包
这个方法需要依赖一些com组件(WHSC30.dll,MSSOAPR3.dll,MSSOAP30.dll,msxml4.dll)
没有这些com dll的机器需要按上面顺序注册一下,注意编译时有的机器也需要注册这些com组件。
HRESULT hr;
ISoapConnectorPtr SoapConnector;
ISoapSerializerPtr Serializer;
ISoapReaderPtr Reader;
try
{
hr = CoInitialize(NULL);//初始化com环境
if(FAILED(hr))
{
OutputDebugString("初始化com环境失败\n");
return " ";
}
CString chNameSpace = "http://sms.ha.mocha.com/"; //命名空间
//创建SoapConnector类的对象
hr = SoapConnector.CreateInstance(__uuidof(HttpConnector30));
if(FAILED(hr))
{
OutputDebugString("创建SoapConnector类的对象失败\n");
return " ";
}//指定Web服务的地址
SoapConnector-> Property["EndPointURL"]= (_bstr_t)"http://sms.ha.mocha.com:8080/haSms/Func";//接口的ip地址//与Web服务连接
hr=SoapConnector-> Connect();
if(FAILED(hr))
{
OutputDebugString("与web服务连接失败\n");
return " ";
}//指定Web服务完成的操作
SoapConnector-> Property ["SoapAction"]= chNameSpace.GetBuffer() + _bstr_t( "Func");
chNameSpace.ReleaseBuffer();//准备发送消息给Web服务
hr=SoapConnector-> BeginMessage();
if(FAILED(hr))
{
OutputDebugString("准备发送消息给Web服务失败\n");
return " ";
}
// 创建SoapSerializer对象
hr=Serializer.CreateInstance(__uuidof(SoapSerializer30));
if(FAILED(hr))
{
OutputDebugString("创建序列化对象失败\n");
return " ";
}
// 将serializer连接到connector的输入字符串
hr=Serializer-> Init(_variant_t((IUnknown*)SoapConnector-> InputStream));
if(FAILED(hr))
{
OutputDebugString("连接到connector失败\n");
return " ";
}
// 创建SOAP消息Serializer->StartEnvelope("soap", "", "");
Serializer->SoapAttribute("xsi", "", "http://www.w3.org/2001/XMLSchema-instance", "xmlns");
Serializer->SoapAttribute("xsd", "", "http://www.w3.org/2001/XMLSchema", "xmlns");
Serializer->StartBody("");
Serializer-> StartElement( "Func", (_bstr_t)chNameSpace, " ", "");
Serializer->SoapAttribute("xmlns", "", (_bstr_t)chNameSpace, "");Serializer-> StartElement( "arg0", (_bstr_t)chNameSpace, "NONE", "");
Serializer->WriteString((_bstr_t)UserName);
Serializer-> EndElement();Serializer-> StartElement( "arg1", (_bstr_t)chNameSpace, "NONE", "");
Serializer->WriteString((_bstr_t)Password);
Serializer-> EndElement();Serializer-> StartElement( "arg2", (_bstr_t)chNameSpace, "NONE", "");
Serializer->WriteString("");
Serializer-> EndElement();
Serializer-> EndElement();
Serializer-> EndBody();
Serializer-> EndEnvelope();//消息真正地发给Web服务
hr=SoapConnector-> EndMessage();
if(FAILED(hr))
{
OutputDebugString("正真发送消息时失败\n");
return " ";
}// 读取响应
Reader.CreateInstance(__uuidof(SoapReader30));// 将reader联接到connector的输出字符串
Reader-> Load(_variant_t((IUnknown*)SoapConnector-> OutputStream), _T( " "));
return CString((const char *)Reader-> RpcResult->text);
}
catch (_com_error e)
{
CString str = (CString)(char*)e.Description();
OutputDebugString(str);
return str;}
3.抛弃接口,直接发送http包。
使用这种办法需要用抓包工具抓到正确的soap包,按照包的格式通过socket向接口地址发送post请求,下面是抓的包
POST /GetList.asmx?op=GetString HTTP/1.0
Content-Type: text/xml; charset=UTF-8
SOAPAction: ""
Accept: */*
User-Agent: Apache CXF 2.2.9
Cache-Control: no-cache
Pragma: no-cache
Host: 192.168.88.247:111
Connection: keep-alive
Content-Length: 279
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sendSms xmlns:ns2="http://sms.ha.mocha.com/"><arg0>vrv</arg0><arg1>123456</arg1><arg2>13691234567</arg2><arg3>...........................:869377</arg3></ns2:sendSms></soap:Body></soap:Envelope>
就按这种格式去发包就可以实现,实际就是用socket将这些字符串发送出去,在接受缓冲区里得到接口返回给我们的数据。具体发送可以搜索一下这个request类。主要代码如下:
int Request::SendHTTP(LPCSTR url,LPCSTR headerReceive,BYTE *post,
DWORD postLength,HTTPRequest *req)
{
WSADATA WsaData;
SOCKADDR_IN sin;
SOCKET sock;
char buffer[512];
char protocol[20],host[256],request[1024];
int l,port,chars,err;
MemBuffer headersBuffer,messageBuffer;
char headerSend[1024];
BOOL done;
ParseURL(url,protocol,sizeof(protocol),host,sizeof(host), // Parse the URL
request,sizeof(request),&port);
if(strcmp(protocol,"HTTP"))
return 1;
err = WSAStartup (0x0101, &WsaData); // Init Winsock
if(err!=0)
return 1;
sock = socket (AF_INET, SOCK_STREAM, 0);
//if (socket == INVALID_SOCKET)
if (sock == INVALID_SOCKET)
{
OutputDebugString("创建套接字失败!\n");
return 1;
}
/*//设置非阻塞
unsigned long uFlag = 1;
int nRet = ioctlsocket(sock,FIONBIO,(unsigned long*)&uFlag);
if(nRet == SOCKET_ERROR)
return 1;*/
sin.sin_family = AF_INET; //Connect to web sever
sin.sin_port = htons( (unsigned short)port );
sin.sin_addr.s_addr = GetHostAddress(host);
if( connect (sock,(LPSOCKADDR)&sin, sizeof(SOCKADDR_IN) ) )
{
OutputDebugString("sokcet 连接失败!\n");
return 1;
}
if( !*request )
lstrcpyn(request,"/",sizeof(request));
if( post == NULL )
{
SendString(sock,"GET ");
strcpy(headerSend, "GET ");
}
else
{
SendString(sock,"POST ");
strcpy(headerSend, "POST ");
}
SendString(sock,request);
strcat(headerSend, request);
SendString(sock," HTTP/1.0\r\n");
strcat(headerSend, " HTTP/1.0\r\n");
if( (headerReceive!=NULL) && *headerReceive )
{
SendString(sock,headerReceive);
strcat(headerSend, headerReceive);
}
SendString(sock, "SOAPAction: \"\"\r\n");
strcat(headerSend, "SOAPAction: \"\"\r\n");
SendString(sock,"Accept: */*\r\n");
strcat(headerSend, "Accept: */*\r\n");
SendString(sock,"User-Agent: Apache CXF 2.2.9\r\n");
strcat(headerSend, "User-Agent: Apache CXF 2.2.9\r\n");
SendString(sock, "Cache-Control: no-cache\r\n");
strcat(headerSend, "Cache-Control: no-cache\r\n");
SendString(sock, "Pragma: no-cache\r\n");
strcat(headerSend, "Pragma: no-cache\r\n");
SendString(sock,"Host: ");
strcat(headerSend, "Host: ");
//将地址格式化
char buf[10]={0};
itoa(port, buf, 10);
strcat(host,":");
strcat(host, buf);
SendString(sock,host);
strcat(headerSend, host);
SendString(sock,"\r\n");
strcat(headerSend, "\r\n");
SendString(sock, "Connection: keep-alive\r\n");
strcat(headerSend, "Connection: keep-alive\r\n");
if(postLength)
{
wsprintf(buffer,"Content-Length: %ld\r\n",postLength);
SendString(sock,buffer);
strcat(headerSend, buffer);
}
SendString(sock,"\r\n"); // Send a blank line to signal end of HTTP headerReceive
strcat(headerSend, "\r\n");
if( (post!=NULL) && postLength )
{
send(sock,(const char*)post,postLength,0);
post[postLength] = '\0';
strcat(headerSend, (const char*)post);
}
req->headerSend = (char*) malloc( sizeof(char*) * strlen(headerSend));
strcpy(req->headerSend, (char*) headerSend );
MemBufferCreate(&headersBuffer );
chars = 0;
done = FALSE;
//接受接口返回的数据。
while(!done)
{
l = recv(sock,buffer,1,0);
if(l<0)
done=TRUE;
switch(*buffer)
{
case '\r':
break;
case '\n':
if(chars==0)
done = TRUE;
chars=0;
break;
default:
chars++;
break;
}
MemBufferAddByte(&headersBuffer,*buffer);
}
req->headerReceive = (char*) headersBuffer.buffer;
*(headersBuffer.position) = 0;
MemBufferCreate(&messageBuffer); // Now read the HTTP body
do
{
l = recv(sock,buffer,sizeof(buffer)-1,0);
if(l<0)
break;
*(buffer+l)=0;
MemBufferAddBuffer(&messageBuffer, (unsigned char*)&buffer, l);
} while(l>0);
*messageBuffer.position = 0;
req->message = (char*) messageBuffer.buffer;
req->messageLength = (messageBuffer.position - messageBuffer.buffer);
closesocket(sock); // Cleanup
return 0;
}
vc 与webservice通信的几种方法
最新推荐文章于 2024-06-28 17:17:58 发布