交代一下故事背景,国内某保险公司,最近上ILOG规则引擎项目,题外话,
对于保险里面的车险核保,真的是相当合适.据说,目前规则引擎最成功的就是ILOG了,我稍微看了一下他们的规则描述语言,感觉好傻啊,用中文描述,我觉得这东西要是可以用导图的那种方式,很发散的方式去处理一定很完美!
回到正题上,因为公司的核心业务系统是使用pro*c编写的服务运行于IBM AIX上面,并且通过中间件与前端通讯,怎么与java的ILOG规则引擎通讯呢?刚开始想着通过gSoap来实现c对web service的调用,但最后因为安装这个包肯定得通过系统管理员,相当麻烦,而且从来没有用过,不知道是否好用,所以ILOG那边增加一个DTO转换层,即将我们发送过去的xml转换成web services调用,并将返回结果也转换成XML;简单的说就是核心后台通过HTTP POST打包xml发送请求,并且规则引擎那边也返回xml来实现!
晕,走题有点严重!
其实无非要实现有两点,
- TCP客户端的模型
- HTTP POST协议
先来看看我的TCP模型的实现
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
上面的代码应该也不用说太多,光看这个这些函数的命名也差不多知道嘛意思了
定义一个结构体,有远程IP及端口,连接状态(注:连接状态是为了保持长连接用的,但事实上post请求的时候,根本就没有保持,所以,基本上没用)
然后是五个tcp函数
tuobao_tcpclient_create:根据服务器IP或者域名,以及端口填充tcpclient结构,主要是申请个socket及填一下sockaddr_in
tuobao_tcpclient_conn:连接到远程端口,并修改tcpclient的连接状态
tuobao_tcpclient_recv:接收远程指定字节数的数据,并分配空间到lpBuf,如果size为0,就阻塞直到连接关闭
tuobao_tcpclient_send:发送buf,size为buf长度
tuobao_tcpclient_close:关闭socket并且设置连接状态
好了,直接贴代码算了
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "tuobao_tcpclient.h"
#define BUFFER_SIZE 1024
int tuobao_tcpclient_create(tuobao_tcpclient *pclient,const char *host, int port){
struct hostent *he;
if(pclient == NULL) return -1;
memset(pclient,0,sizeof(tuobao_tcpclient));
if((he = gethostbyname(host))==NULL){
return -2;
}
pclient->remote_port = port;
strcpy(pclient->remote_ip,inet_ntoa( *((struct in_addr *)he->h_addr) ));
pclient->_addr.sin_family = AF_INET;
pclient->_addr.sin_port = htons(pclient->remote_port);
pclient->_addr.sin_addr = *((struct in_addr *)he->h_addr);
if((pclient->socket = socket(AF_INET,SOCK_STREAM,0))==-1){
return -3;
}
/*TODO:是否应该释放内存呢?*/
return 0;
}
int tuobao_tcpclient_conn(tuobao_tcpclient *pclient){
if(pclient->connected)
return 1;
if(connect(pclient->socket, (struct sockaddr *)&pclient->_addr,sizeof(struct sockaddr))==-1){
return -1;
}
pclient->connected = 1;
return 0;
}
int tuobao_tcpclient_recv(tuobao_tcpclient *pclient,char **lpbuff,int size){
int recvnum=0,tmpres=0;
char buff[BUFFER_SIZE];
*lpbuff = NULL;
while(recvnum < size || size==0){
tmpres = recv(pclient->socket, buff,BUFFER_SIZE,0);
if(tmpres <= 0)
break;
recvnum += tmpres;
if(*lpbuff == NULL){
*lpbuff = (char*)malloc(recvnum);
if(*lpbuff == NULL)
return -2;
}else{
*lpbuff = (char*)realloc(*lpbuff,recvnum);
if(*lpbuff == NULL)
return -2;
}
memcpy(*lpbuff+recvnum-tmpres,buff,tmpres);
}
return recvnum;
}
int tuobao_tcpclient_send(tuobao_tcpclient *pclient,char *buff,int size){
int sent=0,tmpres=0;
while(sent < size){
tmpres = send(pclient->socket,buff+sent,size-sent,0);
if(tmpres == -1){
return -1;
}
sent += tmpres;
}
return sent;
}
int tuobao_tcpclient_close(tuobao_tcpclient *pclient){
close(pclient->socket);
pclient->connected = 0;
}
现在来看看http协议的头吧
虽然搞好几年的asp.net,但是因为微软为我们封装得太好了,一直没有关注http协议的post头应该是怎么样?
想想,其实很简单,看看人家IE是怎么发出去的就知道了
ubuntu下,先用nc工作监听一下,win下面随便发个请求
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
<FORM METHOD=POST ACTION="http://192.168.1.103/a.b">
<INPUT TYPE="text" NAME="input1">
<INPUT TYPE="submit">
</FORM>
看nc的响应
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
好了,基本上知道post请求的http头
下面直接看代码
int http_post(tuobao_tcpclient * pclient, char * page, char * request, char ** response){
char post[ 300 ],host[ 100 ],content_len[ 100 ];
char * lpbuf, * ptmp;
int len = 0 ;
lpbuf = NULL;
const char * header2 = " User-Agent: Tuobao Http 0.1\r\nCache-Control: no-cache\r\nContent-Type: application/x-www-form-urlencoded\r\nAccept: */*\r\n " ;
sprintf(post, " POST %s HTTP/1.0\r\n " ,page);
sprintf(host, " HOST: %s:%d\r\n " ,pclient -> remote_ip,pclient -> remote_port);
sprintf(content_len, " Content-Length: %d\r\n\r\n " ,strlen(request));
len = strlen(post) + strlen(host) + strlen(header2) + strlen(content_len) + strlen(request)+1;
lpbuf = ( char * )malloc(len);
if (lpbuf == NULL){
return - 1 ;
}
strcpy(lpbuf,post);
strcat(lpbuf,host);
strcat(lpbuf,header2);
strcat(lpbuf,content_len);
strcat(lpbuf,request);
if ( ! pclient -> connected){
tuobao_tcpclient_conn(pclient);
}
if (tuobao_tcpclient_send(pclient,lpbuf,len) < 0 ){
return - 1 ;
}
printf( " 发送请求:\n%s\n " ,lpbuf);
/* 释放内存 */
if (lpbuf != NULL) free(lpbuf);
lpbuf = NULL;
/* it's time to recv from server */
if (tuobao_tcpclient_recv(pclient, & lpbuf, 0 ) <= 0 ){
if (lpbuf) free(lpbuf);
return - 2 ;
}
printf( " 接收响应:\n%s\n " ,lpbuf);
/* 响应代码,|HTTP/1.0 200 OK|
*从第10个字符开始,第3位
* */
memset(post, 0 , sizeof (post));
strncpy(post,lpbuf + 9 , 3 );
if (atoi(post) != 200 ){
if (lpbuf) free(lpbuf);
return atoi(post);
}
ptmp = ( char * )strstr(lpbuf, " \r\n\r\n " );
if (ptmp == NULL){
free(lpbuf);
return - 3 ;
}
ptmp += 4 ; /* 跳过\r\n */
len = strlen(ptmp) + 1 ;
* response = ( char * )malloc(len);
if ( * response == NULL){
if (lpbuf) free(lpbuf);
return - 1 ;
}
memset( * response, 0 ,len);
memcpy( * response,ptmp,len - 1 );
/* 从头域找到内容长度,如果没有找到则不处理 */
ptmp = ( char * )strstr(lpbuf, " Content-Length: " );
if (ptmp != NULL){
char * ptmp2;
ptmp += 15 ;
ptmp2 = ( char * )strstr(ptmp, " \r\n " );
if (ptmp2 != NULL){
memset(post, 0 , sizeof (post));
strncpy(post,ptmp,ptmp2 - ptmp);
if (atoi(post) < len)
( * response)[atoi(post)] = ' \0 ' ;
}
}
if (lpbuf) free(lpbuf);
return 0 ;
}
int main(){
tuobao_tcpclient client;
char * response = NULL;
printf( " 开始组包\n " );
tuobao_tcpclient_create( & client, " 127.0.0.1 " , 80 );
if (http_post( & client, " /i.php " , " f1=hello " , & response)){
printf( " 失败!\n " );
exit( 2 );
}
printf( " 响应:\n%d:%s\n " ,strlen(response),response);
free(response);
return 0 ;
}
写个简单的makefile
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
好了,万事OK了。。