5

私はPthreads(私はさらに多くを吸う)を使用してC(私が吸う)でWebサーバーを書いています、そして私はこの時点で立ち往生しています。サーバーのモデルはboss-workerであるため、ボススレッドはプログラムの開始時にすべてのワーカースレッドをインスタンス化します。着信接続のソケットを格納するグローバルキューがあります。ボススレッドは、接続が受け入れられるときにすべてのアイテム(ソケット)をキューに追加するスレッドです。次に、すべてのワーカースレッドは、アイテムがグローバルキューに追加されるのを待って、処理を開始します。

サーバーに接続する回数がサーバーのワーカースレッドの数より少ない限り、サーバーは正常に動作します。そのため、ミューテックスに問題があるか(シグナルが失われている可能性がありますか?)、スレッドが1回実行された後に無効になっていると思います(8つのスレッドがある場合、最初のスレッドしか解析できない理由を説明します) 8つのhttpリクエスト)。

これが私のグローバルキュー変数です。

int queue[QUEUE_SIZE];

これがメインスレッドです。enqueue、dequeue、emptyなどのメソッドを使用してキュー構造体(他の場所で定義)を作成します。サーバーが接続を受け入れると、着信接続がオンになっているソケットをエンキューします。最初にディスパッチされたワーカースレッドは、このキューを常にチェックして、ジョブが追加されているかどうかを確認します。ジョブがある場合は、ソケットをデキューし、そのポートに接続して、着信httpリクエストの読み取り/解析/書き込みを行います。 。

int main(int argc, char* argv[])
{
int hSocket, hServerSocket;  /* handle to socket */
struct hostent* pHostInfo;   /* holds info about a machine */
struct sockaddr_in Address; /* Internet socket address stuct */
int nAddressSize = sizeof(struct sockaddr_in);
int nHostPort;
int numThreads;
int i;

init(&head,&tail);

//**********************************************
//ALL OF THIS JUST SETS UP SERVER (ADDR STRUCT,PORT,HOST INFO, ETC)
if(argc < 3) {
    printf("\nserver-usage port-num num-thread\n");
    return 0;
}
else {
    nHostPort=atoi(argv[1]);
    numThreads=atoi(argv[2]);
}

printf("\nStarting server");

printf("\nMaking socket");
/* make a socket */
hServerSocket=socket(AF_INET,SOCK_STREAM,0);

if(hServerSocket == SOCKET_ERROR)
{
    printf("\nCould not make a socket\n");
    return 0;
}

/* fill address struct */
Address.sin_addr.s_addr = INADDR_ANY;
Address.sin_port = htons(nHostPort);
Address.sin_family = AF_INET;

printf("\nBinding to port %d\n",nHostPort);

/* bind to a port */
if(bind(hServerSocket,(struct sockaddr*)&Address,sizeof(Address)) == SOCKET_ERROR) {
    printf("\nCould not connect to host\n");
    return 0;
}
/*  get port number */
getsockname(hServerSocket, (struct sockaddr *) &Address,(socklen_t *)&nAddressSize);

printf("Opened socket as fd (%d) on port (%d) for stream i/o\n",hServerSocket, ntohs(Address.sin_port));

printf("Server\n\
      sin_family        = %d\n\
      sin_addr.s_addr   = %d\n\
      sin_port          = %d\n"
      , Address.sin_family
      , Address.sin_addr.s_addr
      , ntohs(Address.sin_port)
    );
//Up to this point is boring server set up stuff. I need help below this.
//**********************************************

//instantiate all threads
pthread_t tid[numThreads];

for(i = 0; i < numThreads; i++) {
    pthread_create(&tid[i],NULL,worker,NULL);
}

printf("\nMaking a listen queue of %d elements",QUEUE_SIZE);
/* establish listen queue */
if(listen(hServerSocket,QUEUE_SIZE) == SOCKET_ERROR) {
    printf("\nCould not listen\n");
    return 0;
}

while(1) {

    pthread_mutex_lock(&mtx);
    printf("\nWaiting for a connection");

    while(!empty(head,tail)) {
        pthread_cond_wait (&cond2, &mtx);
    }

    /* get the connected socket */
    hSocket = accept(hServerSocket,(struct sockaddr*)&Address,(socklen_t *)&nAddressSize);

    printf("\nGot a connection");

    enqueue(queue,&tail,hSocket);

    pthread_mutex_unlock(&mtx);
    pthread_cond_signal(&cond);     // wake worker thread
}
}

これがワーカースレッドです。これは常に新しいリクエストのチェックを実行している必要があります(キューが空でないかどうかを確認することによって)。このメソッドの最後では、ボススレッドに戻って、次に必要になるまで待機する必要があります。

void *worker(void *threadarg) {

pthread_mutex_lock(&mtx);

while(empty(head,tail)) {
    pthread_cond_wait(&cond, &mtx);
}
int hSocket = dequeue(queue,&head);

unsigned nSendAmount, nRecvAmount;
char line[BUFFER_SIZE];

nRecvAmount = read(hSocket,line,sizeof line);
printf("\nReceived %s from client\n",line);


//***********************************************
//DO ALL HTTP PARSING (Removed for the sake of space; I can add it back if needed)
//*********************************************** 


nSendAmount = write(hSocket,allText,sizeof(allText));

if(nSendAmount != -1) {
    totalBytesSent = totalBytesSent + nSendAmount;
}
printf("\nSending result: \"%s\" back to client\n",allText);

printf("\nClosing the socket");
/* close socket */
if(close(hSocket) == SOCKET_ERROR) {
    printf("\nCould not close socket\n");
    return 0;
}


pthread_mutex_unlock(&mtx);
pthread_cond_signal(&cond2);
}

どんな助けでも大歓迎です。誰かがそれを必要とするならば、私はもっと多くのコードを投稿することができます、ただ私に知らせてください。私はOSのこと、特にCのことは得意ではありませんが、ミューテックスの基本は知っています。変数、セマフォなど。私が言ったように、私は私が得ることができるすべての助けを借ります。(また、これが私の最初の質問なので、コードを正確に投稿したかどうかはわかりません。読みやすくするためにフォーマットを変更する必要があるかどうかをお知らせください。)

ありがとう!

4

1 に答える 1

5

労働者革命の時。

作業スレッドにwhile(true)ループがないようです。HTTP交換とソケットのクローズの後、それらはループバックして、さらにソケット/リクエストをキューで待機する必要があります。

于 2012-09-30T11:30:04.900 に答える