這是關於一個只有ANSI C標準庫的嵌入式系統的soap客戶端的實現測試。從套接字讀取響應時,我得到了我之前寫的內容
將我的HTTP POST請求發送到服務器後,我試圖在response
上保存SOAP XML文檔。但是當我打印我得到的響應時,除了整個XML文檔之外,它還附加了寫在套接字上的最後223個字節。
由於docbuff_size = 1024
和response
以883個字符結尾,似乎並不是內存重疊問題。我雖然UTF-8編碼可能是一個問題,但我嘗試了不同的尺寸docbuff_size
和buffer_size
,我總是得到相同的行爲。
如果我在標準輸出上使用fputs
編寫我的buffer
,那麼這些尾隨223個字節將不會顯示。我從buffer
的內容構建response
與strncpy
。我認爲這個問題隱藏在這兩個函數的不同行爲上。
這是我的代碼消化版本
...
int n;
char limiter[] = "\r\n\r\n";
bool first = true;
bool limiter_found = false;
char *pDocument = NULL;
char *pTmp = NULL;
unsigned int pDoc_len = 0;
char buffer[buffer_size] = {0};
char midbuff[10] = {0};
char response_code[4] = {0};
bzero(tmp, sizeof(tmp));
char *response;
response = malloc(docbuff_size);
bzero(response, sizeof(response));
bTotal = 0;
while ((n = read(serverSocket, buffer, sizeof(buffer)-1)) > 0)
{
buffer[n] = '\0';
...
// Case: limiter found in last iteration, then copy this buffer entirely
if(pDocument != NULL && (bTotal+strlen(buffer)) < docbuff_size){
strncpy(response+bTotal, buffer, strlen(buffer));
bTotal += strlen(buffer);
}
limiter_found = false;
if(pTmp = strstr(buffer, limiter)){
pDocument = pTmp+4;
limiter_found = true;
} else if (!first && (pTmp = strstr(midbuff, limiter))){
// Take out 3 from the tail offset, add 4 from limiter length = 1
pDocument = buffer + (pTmp - midbuff) + 1;
limiter_found = true;
}
if(limiter_found){
strncpy(response, pDocument, strlen(pDocument));
bTotal += strlen(pDocument);
}
if(fputs(buffer, stdout) == EOF)
{
printf("\n Error : Fputs error\n");
}
}
if(response[0] != 0){
printf("\n\nXML Document: \n"
"*************************************\n"
"%s\n"
"*************************************\n", response);
}
if(n < 0)
{
printf("\n Read error \n");
}
if(response){
free(response);
response = NULL;
}
這是輸出
REQUEST SENT:
POST /xxxx/index.php HTTP/1.0
Host: testzzzzz.dev
User-agent: Blahblah
Content-type: text/xml; charset="iso-8859-1"
Content-length: 677
SOAPAction: "http://testzzzzz.dev/xxxx/index.php/ActionXXXX"
<?xml version="1.0" encoding="iso-8859-1"?><SOAP-ENV:Envelope SOAP- ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/1999/XMLSchema"><SOAP-ENV:Body><ns1:ActionXXXX xmlns:ns1="http://testzzzzz.com/xxxx/nusoap" SOAP-ENC:root="1"><v1 xsi:type="xsd:string">Loremipsumdolorsitamet,consecteturadipisicingelit,seddoeiusmodtemporincididuntutlaboreetdoloremagnaaliqua.Utenimadminimveniam,quisnostrudexercitati</v1></ns1:ActionXXXX></SOAP-ENV:Body></SOAP-ENV:Envelope>
HTTP RESPONSE (written by fputs):
HTTP/1.1 200 OK
Date: Tue, 14 Jan 2014 18:11:39 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.4.9-4ubuntu2.4
X-SOAP-Server: DesiteG/0.9.5 (1.123)
Content-Length: 660
Vary: Accept-Encoding
Connection: close
Content-Type: text/xml; charset=UTF-8
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:ActionXXXXResponse xmlns:ns1="http://testzzzzz.com/xxxx/nusoap"><return xsi:type="xsd:string">ResponseStringblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblaResponseString</return></ns1:ActionXXXXResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
XML Document (build by strncpy):
*************************************
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:ActionXXXXResponse xmlns:ns1="http://testzzzzz.com/xxxx/nusoap"><return xsi:type="xsd:string">ResponseStringblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblaResponseString</return></ns1:ActionXXXXResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>type="xsd:string">Loremipsumdolorsitamet,consecteturadipisicingelit,seddoeiusmodtemporincididuntutlaboreetdoloremagnaaliqua.Utenimadminimveniam,quisnostrudexercitati</v1></ns1:ActionXXXX></SOAP-ENV:Body></SOAP-ENV:Envelope>
*************************************
的摘錄如果滾動到左邊你可以看到什麼樣的fputs之間的差異也從什麼strncpy構建。最後兩次迭代(緩衝區獲得兩次使用)。 似乎read
在最後一次迭代放置一些額外的數據緩衝區fputs
正確忽略,但strncpy不會。
----編輯(解決,但我不知道爲什麼)----使用的strcpy,而不是strncpy()函數的
問題解決了。 看來strlen(buffer)
忽略了之前編寫的buffer[n] = '\0'
。
strncpy(dest, src, strlen(src));
與strcpy(dest, src);
不一樣嗎?
我想留下這個問題,直到解釋清楚的原因。
您可能想使用調試器來了解發生了什麼。對於gcc使用選項'-g'編譯符號,然後使用'gdb --args程序名arg1 arg2 ... argn'運行程序。 – alk
注視着代碼:'bzero(response,sizeof(response));'看起來很奇怪,如果'response'真的被聲明爲'char *'。 –
我將使用一個野指針,在你沒有提供的代碼中的某處。如果這個猜測結果是正確的,那麼它不是真正的「解決」,更有趣的時刻等待着你... –