1

マングースを使用して特定のプロジェクト用の非同期サーバーを開発しています。リクエストを受け取ってすぐに応答し、必要なすべての解析を行ってから、元のリクエストで渡された 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 であっても、Web サーバーに到達するリクエストは 3 つだけです。これら 3 つのうち、1 つは URL が破損しており、もう 1 つは XML が破損していました。

スレッドが終了するのを待つために何かが足りないことはわかっています(メインサーバーが停止しないため、それを理解できません)。

誰かここで何か間違ったことを指摘してください!

4

1 に答える 1

2

文字列をより適切に初期化したい場合があります。

次のパッチを OP のコードに適用すると、コンパイルが行われ、出力がより適切に表示されます。

--- main.c.orig 2012-07-07 14:11:41.000000000 +0200
+++ main.c      2012-07-07 14:09:10.000000000 +0200
@@ -4,15 +4,20 @@
  *  Created on: Jun 28, 2012
  *      Author: mfaraz
  */
+#define LIBXML_WRITER_ENABLED

+#include <unistd.h>
 #include <pthread.h>
 #include <string.h>
+#include <stdlib.h>
 #include <stdio.h>
 #include <time.h>
 #include <curl/curl.h>
+#include <libxml2/libxml/xmlstring.h>
 #include <libxml2/libxml/xmlreader.h>
 #include <libxml2/libxml/encoding.h>
 #include <libxml2/libxml/xmlwriter.h>
+#include <libxml2/libxml/tree.h>

 #define MAX_DATA_LEN            (140)
 #define MAX_XML_LEN             (1024)
@@ -33,7 +38,7 @@
 static void *threadCurl(void *newResponse)  {
     pthread_detach(pthread_self());
     struct responseInfo *thisReponse = (struct responseInfo *) newResponse;
-    char thisXML[MAX_XML_LEN], thisURL[MAX_DATA_LEN];
+    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;
@@ -155,7 +160,7 @@
     threadPtr = pthread_attr_setdetachstate(&theAttribs, PTHREAD_CREATE_DETACHED);
     if (threadPtr)  return threadPtr;
     //  Allocate memory for the responseInfo
-    newResponse = malloc(sizeof(struct responseInfo));
+    newResponse = calloc(1, sizeof(struct responseInfo));
     if (newResponse == NULL)    return -1;
     else    printf("Structure MALLOC'ed!\n");
     int xmlLength = strlen(xmlResp);    int xmlLength2 = xmlLength;//293;

ところで: 別の種類のソース レイアウトについて考え始めることをお勧めします (Eclipse を使用しているように見えるので、Ctrl-Shift-F マジック キーの組み合わせをお勧めします ... ;-))。


また、次の行では、ed されるコンテンツが、以前に生成されたスレッド関数によって再度 ed されprintf()ていないことを保証できません。free()

else    printf("Thread Created with ThreadID %lu!\n", newResponse->thread_id);

newResponseすでに編集されている場合free()、アプリは未定義の動作を実行しています。

于 2012-07-07T12:14:26.987 に答える