1,、server端可以編譯成CGI方式執(zhí)行,,而并不是綁定到某個(gè)端口,。
if (argc < 2) // no args: assume this is a CGI application { soap_serve(&soap); // serve request, on soap_destroy(&soap); // dealloc C++ da soap_end(&soap); // dealloc da }
2,、在編譯服務(wù)器及客戶端程序時(shí)一開始把add.h生成的文件添加到工程,,經(jīng)常出現(xiàn)問(wèn)題,,需要自己調(diào)試,。 特別是鏈接時(shí)段,,server/client要與其生成的文件相對(duì)應(yīng),,server調(diào)用生成的soapserver.cpp,client調(diào)用生成的soapclient.cpp文件,。
3,、多線程方式,在windows下建議用pthread_win32庫(kù),,這里給出多線程下的例子,。
(1) gSOAP需要的頭文件:
//gsoap ns service name: calc //gsoap ns service style: rpc //gsoap ns service encoding: encoded //gsoap ns service namespace: http://127.0.0.1:8089/calc.wsdl //gsoap ns service location: http://127.0.0.1:8089/cal //gsoap ns schema namespace: urn:calc
int ns__add(double a, double b, double *result); int ns__sub(double a, double b, double *result); int ns__mul(double a, double b, double *result); int ns__div(double a, double b, double *result); int ns__pow(double a, double b, double *result);
(2) 多線程服務(wù)器關(guān)鍵代碼
#include "calc.nsmap" #include "soapH.h"
//宏與全局變量的定義
#define BACKLOG (100) #define MAX_THR (10) #define MAX_QUEUE (1000)
pthread_mutex_t queue_cs;//隊(duì)列鎖 pthread_cond_t queue_cv;//條件變量 SOAP_SOCKET queue[MAX_QUEUE];//數(shù)組隊(duì)列 int head =0, tail =0;//隊(duì)列頭隊(duì)列尾初始化 void * process_queue(void *);//線程入口函數(shù)
int enqueue(SOAP_SOCKET);//入隊(duì)列函數(shù) SOAP_SOCKET dequeue(void);//出隊(duì)列函數(shù)
//線程入口函數(shù)
void * process_queue(void * soap) { struct soap * tsoap = (struct soap *)soap; for(;;) { tsoap->socket = dequeue(); if (!soap_valid_socket(tsoap->socket)) { break; } soap_serve(tsoap); soap_destroy(tsoap); soap_end(tsoap); } return NULL; }
//入隊(duì)列操作
int enqueue(SOAP_SOCKET sock) { int status = SOAP_OK; int next; pthread_mutex_lock(&queue_cs); next = tail +1; if (next >= MAX_QUEUE) { next = 0; } if (next == head) { status = SOAP_EOM; } else { queue[tail] =sock; tail = next; } pthread_cond_signal(&queue_cv); pthread_mutex_unlock(&queue_cs); return status; }
//出隊(duì)列操作
SOAP_SOCKET dequeue() { SOAP_SOCKET sock; pthread_mutex_lock(&queue_cs); while (head == tail ) { pthread_cond_wait(&queue_cv,&queue_cs); } sock = queue[head++]; if (head >= MAX_QUEUE) { head =0; } pthread_mutex_unlock(&queue_cs); return sock; }
//加法的實(shí)現(xiàn)
int ns__add(struct soap *soap, double a, double b, double *result) { *result = a + b; return SOAP_OK; }
//減法的實(shí)現(xiàn)
int ns__sub(struct soap *soap, double a, double b, double *result) { *result = a - b; return SOAP_OK; }
//乘法的實(shí)現(xiàn)
int ns__mul(struct soap *soap, double a, double b, double *result) { *result = a * b; return SOAP_OK; } //除法的實(shí)現(xiàn)
int ns__div(struct soap *soap, double a, double b, double *result) { if (b) { *result = a / b; } else { char *s = (char*)soap_malloc(soap, 1024); sprintf(s, "Can't">http:///">Can't divide %f by %f", a, b); return soap_sender_fault(soap, "Division by zero", s); } return SOAP_OK; }
//乘方的實(shí)現(xiàn)
int ns__pow(struct soap *soap, double a, double b, double *result) { *result = pow(a, b); if (soap_errno == EDOM) //oap_errno 和errorno類似, 但是和widnows兼容 { char *s = (char*)soap_malloc(soap, 1024); sprintf(s, "Can't take the power of %f to %f", a, b); sprintf(s, "Can't">http:///">Can't take power of %f to %f", a, b); return soap_sender_fault(soap, "Power function domain error", s); } return SOAP_OK; }
//主函數(shù)
int main(int argc,char ** argv) { struct soap ServerSoap; //初始話運(yùn)行時(shí)環(huán)境 soap_init(&ServerSoap); //如果沒有參數(shù),,當(dāng)作CGI程序處理 if (argc <2) { //CGI 風(fēng)格服務(wù)請(qǐng)求,,單線程 soap_serve(&ServerSoap); //清除序列化的類的實(shí)例 soap_destroy(&ServerSoap); //清除序列化的數(shù)據(jù) soap_end(&ServerSoap); } else { struct soap * soap_thr[MAX_THR]; pthread_t tid[MAX_THR]; int i,port = atoi(argv[1]); SOAP_SOCKET m,s; //鎖和條件變量初始化 pthread_mutex_init(&queue_cs,NULL); pthread_cond_init(&queue_cv,NULL); //綁定服務(wù)端口 m = soap_bind(&ServerSoap,NULL,port,BACKLOG); //循環(huán)直至服務(wù)套接字合法 while (!soap_valid_socket(m)) { fprintf(stderr,"Bind port error! "); m = soap_bind(&ServerSoap,NULL,port,BACKLOG); } fprintf(stderr,"socket connection successful %d ",m);
//生成服務(wù)線程 for(i = 0; i <MAX_THR; i++) { soap_thr[i] = soap_copy(&ServerSoap); fprintf(stderr,"Starting thread %d ",i); pthread_create(&tid[i],NULL,(void*(*)(void*))process_queue,(void*)soap_thr[i]); } for(;;) { //接受客戶端的連接 s = soap_accept(&ServerSoap); if (!soap_valid_socket(s)) { if (ServerSoap.errnum) { soap_print_fault(&ServerSoap,stderr); continue; } else { fprintf(stderr,"Server timed out "); break; } } //客戶端的IP地址 fprintf(stderr,"Accepted connection from IP= %d.%d.%d.%d socket = %d ", ((ServerSoap.ip)>>24)&&0xFF,((ServerSoap.ip)>>16)&0xFF,((ServerSoap.ip)>>8)&0xFF,(ServerSoap.ip)&0xFF,(ServerSoap.socket)); //請(qǐng)求的套接字進(jìn)入隊(duì)列,,如果隊(duì)列已滿則循環(huán)等待 while(enqueue(s) == SOAP_EOM){ Sleep(1000); } } //服務(wù)結(jié)束后的清理工作 for(i = 0; i < MAX_THR; i++) { while (enqueue(SOAP_INVALID_SOCKET) == SOAP_EOM) { Sleep(1000); } } for(i=0; i< MAX_THR; i++) { fprintf(stderr,"Waiting for thread %d to terminate ..",i); pthread_join(tid[i],NULL); fprintf(stderr,"terminated "); soap_done(soap_thr[i]); free(soap_thr[i]); } pthread_mutex_destroy(&queue_cs); pthread_cond_destroy(&queue_cv); } //分離運(yùn)行時(shí)的環(huán)境 soap_done(&ServerSoap); return 0; } |
|