首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

gSOAP實現C++ Web Service服務端與PHP客戶端通信實戰

     編輯:關於C語言

項目背景

實現基於SOAP協議的跨語言通信:C++ (gSOAP) 作為服務端,PHP (SoapClient) 作為客戶端。網上流傳的示例多因版本差異、WSDL處理、命名空間映射等問題無法直接運行,本文提供經調試可用的完整方案。

PHP客戶端代碼

 "https://127.0.0.1:8888",
        'uri'      => "urn:add",
        'connection_timeout' => 3
    ));
    
    var_dump($soap);  // 調試:查看可用方法
    
    // 調用遠程方法,參數需關聯數組形式
    $params = array('num1' => 6, 'num2' => 2);
    $result = $soap->add($params);
    
    var_dump($result);
    echo "Sum: " . $result->sum;  // 輸出: Sum: 8
    
} catch (SoapFault $e) {
    echo "SOAP Fault: " . $e->getMessage();
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}
?>

gSOAP服務端核心實現

關鍵文件結構

  • add.h:服務接口定義
  • soapH.h / soapStub.h:gSOAP生成的存根代碼
  • add.nsmap:命名空間映射表
  • add.wsdl:WSDL描述文件(需放置在可讀路徑)

服務端主程序 (server.cpp)

#include "soapH.h"
#include <windows.h>
#include "add.nsmap"

#define BACKLOG 100

DWORD WINAPI process_request(LPVOID*);
int http_get(struct soap*);

int main(int argc, char** argv) {
    struct soap soap;
    soap_init(&soap);
    
    if (argc < 2) {
        // 單線程模式(調試用)
        soap_serve(&soap);
        soap_destroy(&soap);
        soap_end(&soap);
    } else {
        // 多線程服務器模式
        soap.send_timeout = 60;
        soap.recv_timeout = 60;
        soap.accept_timeout = 3600;
        soap.max_keep_alive = 100;
        soap.fget = http_get;  // 掛載HTTP GET處理函數(用於WSDL分發)
        
        int port = atoi(argv[1]);
        SOAP_SOCKET m = soap_bind(&soap, NULL, port, BACKLOG);
        if (!soap_valid_socket(m)) exit(1);
        
        printf("Server listening on port %d\n", port);
        
        for (;;) {
            SOAP_SOCKET s = soap_accept(&soap);
            if (!soap_valid_socket(s)) {
                if (soap.errnum) soap_print_fault(&soap, stderr);
                break;
            }
            
            // 為每個連接創建線程處理
            struct soap* tsoap = soap_copy(&soap);
            DWORD tid;
            HANDLE hThread = CreateThread(NULL, 0, 
                (LPTHREAD_START_ROUTINE)process_request, tsoap, 0, &tid);
            if (!hThread) { printf("Thread creation failed\n"); exit(-1); }
        }
    }
    soap_done(&soap);
    return 0;
}

// 線程處理函數
DWORD WINAPI process_request(LPVOID* arg) {
    struct soap* tsoap = (struct soap*)arg;
    soap_serve(tsoap);
    soap_destroy(tsoap);
    soap_end(tsoap);
    soap_done(tsoap);
    free(tsoap);
    return 0;
}

// 服務方法實現:加法運算
int ns__add(struct soap* soap, int num1, int num2, int* sum) {
    *sum = num1 + num2;
    return SOAP_OK;
}

// HTTP GET處理:分發WSDL文件
int http_get(struct soap* soap) {
    char* s = strchr(soap->path, '?');
    if (!s || strcmp(s, "?wsdl")) return SOAP_GET_METHOD;
    
    FILE* fd = fopen("./add.wsdl", "rb");
    if (!fd) return 404;
    
    soap->http_content = "text/xml";
    soap_response(soap, SOAP_FILE);
    
    for (;;) {
        size_t r = fread(soap->tmpbuf, 1, sizeof(soap->tmpbuf), fd);
        if (!r) break;
        if (soap_send_raw(soap, soap->tmpbuf, r)) break;
    }
    fclose(fd);
    soap_end_send(soap);
    return SOAP_OK;
}

關鍵技術點解析

1. 命名空間映射 (add.nsmap)

struct Namespace namespaces[] = {
    {"SOAP-ENV", "https://schemas.xmlsoap.org/soap/envelope/"},
    {"SOAP-ENC", "https://schemas.xmlsoap.org/soap/encoding/"},
    {"xsi", "https://www.w3.org/2001/XMLSchema-instance"},
    {"xsd", "https://www.w3.org/2001/XMLSchema"},
    {"ns", "urn:add"},  // 服務命名空間,與PHP uri參數對應
    {NULL, NULL}
};

2. 服務接口定義 (add.h)

//gsoap ns service name: add
//gsoap ns service style: rpc
//gsoap ns service encoding: encoded
//gsoap ns service location: https://127.0.0.1:8888
//gsoap ns schema namespace: urn:add

int ns__add(int num1, int num2, int* sum);

3. WSDL文件分發機制

gSOAP服務端需自行處理 ?wsdl 請求,http_get 函數讀取本地 add.wsdl 文件並以 text/xml 內容類型返回,這是PHP SoapClient 獲取服務描述的關鍵。

4. 多線程併發模型

  • 主線程 soap_accept 接受連接
  • 每連接 soap_copy 創建獨立上下文
  • Windows CreateThread 運行 process_request
  • 線程內 soap_serve 處理完整SOAP交互

常見問題排查

問題原因解決
PHP報「Could not connect to host」服務端未啟動/端口阻塞/防火牆檢查服務進程、netstat -an、防火牆規則
WSDL解析失敗WSDL文件路徑錯誤/命名空間不匹配確保http_get正確讀取add.wsdl,nsmap與PHP uri一致
參數傳遞錯誤PHP關聯數組鍵名與WSDL定義不符對照WSDL message part名稱調整$params鍵名
中文亂碼編碼不一致確保WSDL聲明UTF-8,PHP/服務端統一編碼

編譯部署步驟

  1. 安裝gSOAP工具包
  2. 編寫 add.h 接口定義
  3. 運行 soapcpp2 -c -j add.h 生成存根代碼
  4. 實現 ns__add 等服務方法
  5. 編寫主程序,鏈接 libgsoap.a / gsoap++.lib
  6. 編譯生成可執行文件 server.exe
  7. 將 add.wsdl 放置於可執行文件同級目錄
  8. 啟動服務:server.exe 8888
  9. 部署PHP客戶端腳本,訪問測試

總結

gSOAP提供了高性能、標準合規的C++ Web Service實現。關鍵在於:正確的命名空間映射、WSDL文件動態分發、線程安全的上下文管理、與PHP SoapClient的參數格式對接。本方案經實測可在Windows/Linux雙平台穩定運行,適合企業級異構系統集成場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved