我们正在使用 mongoose 为特定项目开发异步服务器。它接受一个请求,给出一个即时响应,执行它需要的所有解析,然后响应在原始请求中传递的 URL。
请求接收部分完美无缺。回应是另一回事。
不能把整个程序放在这里(适当的问题),但我已经能够制作一个副本,这样问题就可以证明了。
/*
* xmlcrlth.c
*
* Created on: Jun 28, 2012
* Author: mfaraz
*/
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <curl/curl.h>
#include <libxml2/libxml/xmlreader.h>
#include <libxml2/libxml/encoding.h>
#include <libxml2/libxml/xmlwriter.h>
#define MAX_DATA_LEN (140)
#define MAX_XML_LEN (1024)
#define MAX_THREAD_STACK (1024 * 1024)
//#define MY_ENCODING "ISO-8859-1"
#define MY_ENCODING "UTF-8"
#define DEFAULT_THREADS 25
//typedef
struct responseInfo {
pthread_t thread_id; /* ID returned by pthread_create() */
int urlLength; /* The Length of the URL */
int xmlLength; /* The Length of the XML */
char theXML[MAX_XML_LEN]; /* The XML to post */
char theURL[MAX_DATA_LEN]; /* The URL to post to */
};
static void *threadCurl(void *newResponse) {
pthread_detach(pthread_self());
struct responseInfo *thisReponse = (struct responseInfo *) newResponse;
char thisXML[MAX_XML_LEN], thisURL[MAX_DATA_LEN];
CURL *curlResponse; /* cURL variable to perform a Response */
CURLcode curlResCode; /* cURL Response Code */
struct curl_slist *headList = NULL;
int urlLength = strlen(thisReponse->theURL); int xmlLength = strlen(thisReponse->theXML);
printf("Received XML (%d vs %d bytes) using ThreadID %lu\n%s \nto URL (%d vs %d bytes) %s\n", xmlLength, thisReponse->xmlLength, thisReponse->thread_id, thisReponse->theXML, urlLength, thisReponse->urlLength, thisReponse->theURL);
// if (urlLength != thisReponse->urlLength)
strncpy(thisURL, thisReponse->theURL, thisReponse->urlLength);
// if (xmlLength != thisReponse->xmlLength)
strncpy(thisXML, thisReponse->theXML, thisReponse->xmlLength);
/*FILE *filePtr; char fileName[MAX_DATA_LEN] = ""; sprintf(fileName, "%lu", pthread_self());
filePtr = fopen(fileName, "a+");
fprintf(filePtr, "-------------------------\n");
fprintf(filePtr, "ThreadID: %s\n", fileName);
fprintf(filePtr, "OurlLength: %d\tCurlLength: %d\n", thisReponse->urlLength, urlLength);
fprintf(filePtr, "OxmlLength: %d\tCxmlLength: %d\n\n", thisReponse->xmlLength, xmlLength);
fprintf(filePtr, "OrigURL: %s\n", thisReponse->theURL);
fprintf(filePtr, "OrigXML: %s\n", thisReponse->theXML);
fprintf(filePtr, "NewURL: %s\n", thisURL);
fprintf(filePtr, "NewXML: %s\n", thisXML);
fclose(filePtr);//*/
urlLength = strlen(thisURL); xmlLength = strlen(thisXML);
printf("Sending XML (%d bytes) using ThreadID %lu\n%s \nto URL (%d bytes) %s\n", xmlLength, thisReponse->thread_id, thisXML, urlLength, thisURL);
headList = curl_slist_append(headList, "Content-Type: text/xml");
curlResponse = curl_easy_init();
if (curlResponse) {
curl_easy_setopt(curlResponse, CURLOPT_URL, thisURL);
curl_easy_setopt(curlResponse, CURLOPT_HTTPHEADER, headList);
// curl_easy_setopt(curlResponse, CURLOPT_POSTFIELDS, xmlResp);
curl_easy_setopt(curlResponse, CURLOPT_POSTFIELDSIZE, thisReponse->xmlLength);
curl_easy_setopt(curlResponse, CURLOPT_COPYPOSTFIELDS, thisXML);
curl_easy_setopt(curlResponse, CURLOPT_CONNECTTIMEOUT, 10);
curl_easy_setopt(curlResponse, CURLOPT_TIMEOUT, 30);
curl_easy_setopt(curlResponse, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curlResponse, CURLOPT_FRESH_CONNECT, 1);
curl_easy_setopt(curlResponse, CURLOPT_FORBID_REUSE, 1);
curlResCode = curl_easy_perform(curlResponse);
if (curlResCode) printf("Curl Failed with status: %s!\n", curl_easy_strerror(curlResCode));
curl_easy_cleanup(curlResponse);
} else {
printf("Curl Init Failed!\n");
curlResCode = CURLE_FAILED_INIT;
}
curl_slist_free_all(headList);
free(thisReponse);
pthread_exit(NULL);
// return (int)curlResCode;
}
char *getXML(int failCode, char *failDesc) {
int rc;
xmlTextWriterPtr writer;
xmlBufferPtr buf;
// xmlChar *tmp;
static char xmlResp[1024]; xmlResp[0] = '\0';
/* Create a new XML buffer, to which the XML document will be written */
buf = xmlBufferCreate(); if (buf == NULL) printf("MTU_smac: Error creating the xml buffer\n");
/* Create a new XmlWriter for memory, with no compression.
* Remark: there is no compression for this kind of xmlTextWriter */
writer = xmlNewTextWriterMemory(buf, 0); if (writer == NULL) printf("MTU_smac: Error creating the xml writer\n");
/* Start the document with the xml default for the version,
* encoding ISO 8859-1 and the default for the standalone
* declaration. */
rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterStartDocument\n");
/* Start an element named "svc_result". Since thist is the first
* element, this will be the root element of the document. */
rc = xmlTextWriterStartElement(writer, (xmlChar *)"svc_result"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterStartElement\n");
/* Start an element named "sli_rep" as child of svc_result. */
rc = xmlTextWriterStartElement(writer, (xmlChar *)"sli_rep"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterStartElement\n");
/* Add an attribute with name "version" and value "1.0" to sli_rep. */
rc = xmlTextWriterWriteAttribute(writer, (xmlChar *)"version", (xmlChar *)"3.0.0"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterWriteAttribute\n");
/* Start an element named "pos" as child of sli_rep. */
rc = xmlTextWriterStartElement(writer, (xmlChar *)"pos"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterStartElement\n");
/* Write an element named "poserr" as child of pos. */
rc = xmlTextWriterStartElement(writer, (xmlChar *)"poserr"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterStartElement\n");
/* Write an element named "time" as child of poserr. */
rc = xmlTextWriterWriteElement(writer, (xmlChar *)"time", (xmlChar *)"Time will Come here"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterWriteFormatElement\n");
/* Add an attribute with name "utc" and value "+0500" to time. */
rc = xmlTextWriterWriteAttribute(writer, (xmlChar *)"utc", (xmlChar *)"+0500"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterWriteAttribute for utc\n");
/* Write an element named "result" as child of poserr. */
rc = xmlTextWriterWriteFormatElement(writer, (xmlChar *)"result", "%s", failDesc); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterWriteFormatElement\n");
/* Add an attribute with name "utc" and value "+0500" to time. */
rc = xmlTextWriterWriteAttribute(writer, (xmlChar *)"resid", (xmlChar *)failCode); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterWriteAttribute for resid\n");
/* Close the element named poserr. */
rc = xmlTextWriterEndElement(writer); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterEndElement\n");
/* Close the element named pos. */
rc = xmlTextWriterEndElement(writer); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterEndElement\n");
/* Start an element named "extra" as child of sli_rep. */
rc = xmlTextWriterStartElement(writer, (xmlChar *)"extra"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterStartElement\n");
/* Write an element named "resp_status" as child of extra. */
rc = xmlTextWriterWriteFormatElement(writer, (xmlChar *)"resp_status", "%d", failCode); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterWriteFormatElement\n");
/* Here we could close the elements sli_rep and svc_result using the
* function xmlTextWriterEndElement, but since we do not want to
* write any other elements, we simply call xmlTextWriterEndDocument,
* which will do all the work. */
rc = xmlTextWriterEndDocument(writer);
if (rc < 0) printf("MTU_smac: Error at xmlTextWriterEndDocument\n");
xmlFreeTextWriter(writer);
// printf("%s\n", (const char *) buf->content);
sprintf(xmlResp, "%s", (const char *) buf->content);
xmlBufferFree(buf);
return xmlResp;
}
int postXMLResponse(char *xmlResp, char *theURL) {
int urlLength = strlen(theURL);
if (urlLength == 0) return 0; // No URL...no Tension...!
struct responseInfo *newResponse;
pthread_attr_t theAttribs;
int threadPtr;
// Init the threading
threadPtr = pthread_attr_init(&theAttribs);
if (threadPtr) return threadPtr;
else printf("Thread Initialized!\n");
// Set the Stack size.
threadPtr = pthread_attr_setstacksize(&theAttribs, MAX_THREAD_STACK);
if (threadPtr) return threadPtr;
else printf("Thread Stack Size set!\n");
// Set the Thread as Detachable.
threadPtr = pthread_attr_setdetachstate(&theAttribs, PTHREAD_CREATE_DETACHED);
if (threadPtr) return threadPtr;
// Allocate memory for the responseInfo
newResponse = malloc(sizeof(struct responseInfo));
if (newResponse == NULL) return -1;
else printf("Structure MALLOC'ed!\n");
int xmlLength = strlen(xmlResp); int xmlLength2 = xmlLength;//293;
newResponse->urlLength = urlLength;
newResponse->xmlLength = xmlLength;
strncpy(newResponse->theURL, theURL, urlLength);
strncpy(newResponse->theXML, xmlResp, xmlLength2);
printf("Threading Send XML (%d bytes)\n%s \nto URL (%d bytes) %s\n", xmlLength, newResponse->theXML, urlLength, newResponse->theURL);
threadPtr = pthread_create(&newResponse->thread_id, &theAttribs, &threadCurl, newResponse);
if (threadPtr) return threadPtr;
else printf("Thread Created with ThreadID %lu!\n", newResponse->thread_id);
/*FILE *filePtr; char fileName[MAX_DATA_LEN] = ""; sprintf(fileName, "%lu", newResponse->thread_id);
filePtr = fopen(fileName, "a");
fprintf(filePtr, "ThreadID: %s\n", fileName);
fprintf(filePtr, "urlLength: %d\n", newResponse->urlLength);
fprintf(filePtr, "xmlLength: %d\n", newResponse->xmlLength);
fprintf(filePtr, "URL: %s\n", newResponse->theURL);
fprintf(filePtr, "XML: %s", newResponse->theXML);
fclose(filePtr);//*/
threadPtr = pthread_attr_destroy(&theAttribs);
if (threadPtr) return threadPtr;
else printf("Thread Attributes!\n");
return 0;
}
int main(int argc, char *argv[]) {
long int iLoop, iMaxCount;
curl_global_init(CURL_GLOBAL_ALL);
iMaxCount = DEFAULT_THREADS;
if (argc > 1) {
// printf("Showing Arguments: -\n"); for (iLoop = 1 ; iLoop < argc ; iLoop++) printf("%lu = %s\n", iLoop + 1, argv[iLoop]);
iMaxCount = strtol(argv[1], NULL, 10);
}
for (iLoop = 0 ; iLoop < iMaxCount ; iLoop++) {
postXMLResponse(getXML(iLoop, "All of your base are belong to us!"), "http://localhost:80/response.php");
}
sleep(3);
return 0;
}
您需要为库设置“xml2”、“curl”和“pthread”,为链接器设置“-pthread”。根据您的设置,您可能还需要为 libxml 库指定实际文件夹。
当你运行程序时,它会尝试生成 25 个线程。第一个参数可以将其更改为适合您进行测试的任何数字。在我的测试中,即使是 5,也只会导致 3 个请求登陆网络服务器。即使在这 3 个中,一个有一个损坏的 URL,一个有一个损坏的 XML。
我知道我在等待线程结束时遗漏了一些东西(无法弄清楚,因为主服务器不会停止)。
有人指出这里有问题!