2016-10-19 11 views
-1

私は、複数のクライアントからの複数の応答を受け入れることによって、サーバーを同時に実行させるさまざまな方法を実践しています。これは学校の割り当てです。CスレッドHttpサーバーエラー

私は現在、スレッド処理に問題があります。スレッド動作しますが、

「カール:(56)のrecv失敗:ピアによって接続がリセットさ」のエラーを取得

をこれは私のスレッドはに行く応答関数であるためのラインです。クライアント[n]以外のすべての変数はかなり定数です。だから、それはむしろ右に通過しないか、私は完全にスレッディングが行われる必要があります上の印を紛失しています。この行はRCVDに-1を返す保持し、私は> 0

をしたい

rcvd = recv(clients[n], mesg, 99999, 0); 

は、ここに私のコードです。

#include<stdio.h> 
#include<string.h> 
#include<stdlib.h> 
#include<unistd.h> 
#include<sys/types.h> 
#include<sys/stat.h> 
#include<sys/socket.h> 
#include<arpa/inet.h> 
#include<netdb.h> 
#include<signal.h> 
#include<fcntl.h> 
#include<pthread.h> 

#include "functions.h" 
#define CONNMAX 1000 
#define BYTES 1024 

char *ROOT; 
int verbose; 
int signalReceived = 1; 
int listenfd, clients[CONNMAX], slot; 
pthread_t thread; 
void error(char *); 

void *threadServer(void *arg) 
{ 
    printf("bong"); 
    respond(slot, verbose, ROOT, clients); 
    exit(0); 
} 

void clean(int arg) 
{ 
    signalReceived = 0; 
} 

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

    signal(SIGINT, clean); 
    signal(SIGHUP, clean); 

    struct sockaddr_in clientaddr; 
    socklen_t addrlen; 
    char c; 
    char PORT[6]; 
    ROOT = getenv("PWD"); 
    strcpy(PORT, "8888"); 
    while ((c = getopt (argc, argv, "p:v")) != -1) 

    switch (c) 
    { 
     case'v': 
     verbose = 1; 
     break; 

     case'p': 
     strcpy(PORT, optarg); 
     break; 

     case'?': 
     fprintf(stderr, "Wrong arguments given\n"); 
     exit(1); 

     default: 
     exit(1); 
    } 
    printf("Listening on port %s%s%s, root is %s%s%s\n", "\033[92m", PORT, "\033[0m", "\033[92m", ROOT, "\033[0m"); 
    int i = 0; 
    for (i = 0; i < CONNMAX; i++) 
     clients[i] = -1; 
    startServer(PORT, &listenfd); 

    while (signalReceived == 1) 
    { 
     addrlen = sizeof(clientaddr); 
     clients[slot] = accept (listenfd, (struct sockaddr *) &clientaddr, &addrlen); 

     if (clients[slot] < 0) 
     exit(0); 

     else 
     { 
      printf("bang"); 
      pthread_create(&thread, NULL, threadServer, NULL); 
     } 
     while (clients[slot] != -1) 
      slot = (slot + 1) % CONNMAX; 
    } 
    return 0; 
} 

私が学んでいる、これが私の元のソースワーク、学習するためではなく、編集作業ではありません。私はフォークされた元のプログラムをとり、スレッドプログラムに変換しようとしています。

+0

'startServer'とは何ですか? '応答する 'とは何ですか?コードを見ることはできますか? –

+0

スレッドで 'exit'を呼び出します。 'exit'は* process *を終了します。 'threadServer'からの' return'もありません( 'return NULL'おそらく?)。また、あなたの 'main'関数で同時に変更する* threadServer内のグローバル変数も使用しています。 – kfsone

答えて

0

slotはグローバル変数です。スレッドの開始には少し時間がかかりますが、スレッドは同じメモリを共有します。フォークされたプロセスのような独自のスナップショットはありません。

スレッドを開始すると、メインプロセスが変更されます。slotとなります。

ベストケースのシナリオ:新しいスレッドが開始され、新しいの値がconnections[slot] == -1になるようにします。最悪の場合:スレッドが異なるCPUコアで実行され、slotを取得し、がメインに書き込みを行っているため、値が不正です。あなたが代わりにスレッド関数へのパラメータとしてslotを渡すことを検討する必要があります

:あなたがここにある

void *threadServer(void *arg) 
{ 
    int mySlot = (int)arg; 
    printf("bong\n"); 
    respond(mySlot, verbose, ROOT, clients); 
    clients[mySlot] = -1; 
    printf("bash\n"); 
    return NULL; // calling 'exit' terminates the whole process. duh. 
} 

// ... 

    pthread_create(&thread, NULL, threadServer, (void*)slot); 

もう一つの問題は、これらすべてのスレッドを作成していますが、個別にそれらを追跡していないということです。おそらく、スレッドの配列が必要な場合や、単純な構造体を考えたい場合があります:

typedef struct Clients { 
    int fd; 
    pthread_t thread; 
} Clients; 
Clients clients[MAXCONN]; 

// 

while (signalReceived == 1) 
{ 
    addrlen = sizeof(clientaddr); 
    clients[slot].fd = accept(listenfd, (struct sockaddr *) &clientaddr, &addrlen); 

    if (clients[slot].fd < 0) 
     exit(0); 
    else 
    { 
     printf("bang"); 
     pthread_create(&clients[slot].thread, NULL, threadServer, (void*)slot); 
    } 

    while (clients[slot] != -1) 
     slot = (slot + 1) % CONNMAX; // what if we can't find one? 
} 
+0

本当に有益です – TheMangaStand

0

threadServer関数はexitを呼び出し、処理を終了します。

forkを呼び出すサーバーでは適切ではないため、どこから来たのかわかりません。しかし、マルチスレッドプログラムでは間違いなく致命的です。

+0

それは問題ではないようです。私が退出を呼び出す前に、それは失敗するようです。 curl http:// localhost:8888/textを送信すると失敗します。txt – TheMangaStand

+0

私のレスポンス関数もコードで与えるべきですか? – TheMangaStand

+0

あなたは決して 'slot'を設定しませんが、あなたは' clients [slot] = ... 'を実行します。 –

関連する問題