0

私はpthreadライブラリから始めており、このような関数を数回並行して実行したいと思います。

while(true) {
    //Part A
    //do several stuff
    //End of Part A

    //Part B
    //do other stuffs
    //End of Part B
}

pthread_create()をロッピングすることで、これを簡単に行うことができます。問題は、パートBが実行される前にメインプログラムがスレッドを切り替えているように見えることです。その結果、パートAが何度も実行されているのがわかりますが、パートBは実行されていません。誰か助けてもらえますか?

いくつかの実際のコード=>

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pthread.h>

#define error(msg) \
        perror(msg); \
        exit(EXIT_FAILURE)


//Declarations
int mastersocket;
struct sockaddr_in addr;
struct hostent *fromhost, *tohost;
int nthread=5;
int  decdomain=13;
long serveurdns=0x0101a8c0;

static void * test(void * p_data) {

    while(1) {
        printf("hello\n");
    }
    return NULL;
}

int main(int argc, char **argv) {

        int k, l;
        pthread_t idt[5];

    //Assignation, mallocs
    //Strings

    //Appel a socket
    if( (mastersocket=socket(PF_INET, SOCK_DGRAM, 0)) < 0 ) {
        error("socket");
    }

    //Configuration de sockaddr pour l'appel a bind
    addr.sin_family=AF_INET;
    addr.sin_addr.s_addr=htonl(INADDR_ANY);
    addr.sin_port=htons(53);

    //Appel a bind
    if( (bind(mastersocket, (struct sockaddr *)&addr, sizeof(addr))) < 0 ) {
        error("bind");
    }

    for(k=0; k<nthread; k++) {

        pthread_create(&idt[k], NULL, mainbis, (void *)mastersocket);

    }
    mainbis((void *)mastersocket);

    return 0;

}

static void * mainbis(void * p_data) {

    int socketh= (int) p_data;
    int found=0, len, cc;
    char *buf, *curfish;
    struct sockaddr_in *from, *to;
    u_long fromaddr, toaddr;
    int lenbuf=5000;

    buf=(char *)malloc(lenbuf);
    curfish=(char *)malloc(100);

    len=sizeof(struct sockaddr_in);
    to=(struct sockaddr_in *)malloc(len);
    from=(struct sockaddr_in *)malloc(len);
    //Structure sockaddr du serveur DNS vers lequel on redirige les requete
    to->sin_family=AF_INET; 
    to->sin_addr.s_addr=serveurdns;
    to->sin_port=htons(53);

    //Let's go
    while(1) {

        found=0;
        curfish=NULL;
        //Reception des requetes
        if((cc=recvfrom(socketh, buf, lenbuf, 0, (struct sockaddr *)from, &len))<0) {
            error("recv");
        }
        buf[cc]='\0';

        //Identification de l'host appelant
        //fromaddr=(*from).sin_addr.s_addr;
        //fromhost=gethostbyaddr((void *)&fromaddr, sizeof(fromaddr), AF_INET);

        //Sortie utilisateur
        printf("\n\n--   New Request From $$ on Port ... Domain = %s ||\n--  ***********************\n", buf+13);

        curfish=somefunction();
        if( curfish!=NULL ) {

            found=1;

        }

        if(sendto(socketh, buf, cc, 0, (struct sockaddr *)to, len)<0) {
            error("send");
        }

        if((cc=recvfrom(socketh, buf, lenbuf, 0, (struct sockaddr *)to, &len))<0) {
            error("recv");
        }
        buf[cc]='\0';

        printf("\n\n--   New Response From $$ on Port ||\n--  ***********************\n");

        if(found) {

            buf[cc-1]=0x81;
            buf[cc-2]=0x2;
            buf[cc-3]=0xa8;
            buf[cc-4]=0xc0;

        }

        if(sendto(socketh, buf, cc, 0, (struct sockaddr *)from, len)<0) {
            error("send");
        }

    }
    return NULL;

}

これはDNS要求のUDPリダイレクタです。たとえば、digを起動して使用しようとすると、プログラムは常に「New Request ...」文字列を出力しますが、「NewResponse...」文字列を出力することはありません。

ジュール

4

1 に答える 1

1

あなたのコードは機能しません。1 つの socket をバインドmastersocketし、このソケットを使用して複数のスレッドを作成します。

これ自体は問題ありませんが、mainbis() 内のロジックは、送信したものに対する応答を読み取ることを前提としています。それが起こらない可能性があり、同じソケットでブロックしている、作成した他のスレッドによって応答が読み取られる可能性がrecvfromあり、ロジックが崩壊します。

実際の dns サーバーとの通信に使用する各スレッドに新しいソケットを作成sockethし、クライアントとの通信にのみ使用します。

于 2012-12-17T15:14:53.440 に答える