2011-09-14 12 views
0

私は以下のようなクライアントプログラムを持っており、マルチスレッド化する必要があります。しかし、変数sockfdは1つのスレッドに対してグローバルに保持されます。私はこれを行うことを理解しています。私はpthread_key_t、pthread_key_create ...などを使う必要があります。しかし、私はそれを使用する方法が混乱しています。私はどんな助けにも感謝しています。スレッド固有のデータ

int sockfd; 
pthread_key_t key_to_sockfd; 

void error(const char *msg) 
{ 
    perror(msg); 
    exit(0); 
} 


void set_connection(char *argv[]) 
{ 

    int portno; 
    struct sockaddr_in serv_addr; 
    struct hostent *server; 

    char buffer[256]; 
    portno = atoi(argv[2]); 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0) 
     error("ERROR opening socket"); 
    server = gethostbyname(argv[1]); 
    if (server == NULL) { 
     fprintf(stderr,"ERROR, no such host\n"); 
     exit(0); 
} 
bzero((char *) &serv_addr, sizeof(serv_addr)); 
serv_addr.sin_family = AF_INET; 
bcopy((char *)server->h_addr, 
(char *)&serv_addr.sin_addr.s_addr,server->h_length); 
serv_addr.sin_port = htons(portno); 
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
    error("ERROR connecting"); 
return; 
} 

void send_message() 
{ 
    char buffer[256]; 
    int i=0,n; 
    do{ 
     printf("Please enter the message: "); 
     bzero(buffer,256); 
     fgets(buffer,255,stdin); 
     n = write(sockfd,buffer,strlen(buffer)); 
     if (n < 0) 
     error("ERROR writing to socket"); 
    i++; 
}while(i<3); 
bzero(buffer,256); 
n = read(sockfd,buffer,255); 
if (n < 0) 
    error("ERROR reading from socket"); 
printf("%s\n",buffer); 
return; 
} 

void disconnect() 
{ 
    close(sockfd); 
    return; 
} 

void client_thrd(char *argv[]) 
{ 
    set_connection(argv); 
    send_message(); 
    disconnect(); 
} 
int main(int argc, char *argv[]) 
{ 

pthread_t thid[2]; 
int i; 
void *status; 
if (argc < 3) { 
    fprintf(stderr,"usage %s hostname port\n", argv[0]); 
    exit(0); 
} 
for(i=0;i<1;i++) 
    pthread_create(&thid[i],NULL,(void*)&client_thrd,(void*)argv); 
for(i=0;i<1;i++) 
    pthread_join(thid[i],&status); 


return 0; 
} 

私は1つのスレッドのためのプログラムを実行し、正常に動作します。しかし、スレッドの数を増やすにつれて、グローバルなvaiable sockfdのためにはうまくいきません。これははるかに大きなもののためのテストプログラムです。

ありがとうございます。

+0

はこの質問をクローズする必要があり、また、それがdownvotedれた理由を私に知らせてください –

+0

親愛なるdownvoterをdownvoted理由を学ぶために感謝するでしょう。 –

+0

@downvoter上記のコメントを読んでください。 :) –

答えて

3

非常に使いやすいです。プログラムの最初にpthread_key_create(&key_to_sockfd, NULL)を呼び出した後、各スレッドで初期値NULLが表示されます。各スレッドでpthread_setspecific(key_to_sockfd, <pointer to a struct which contains sockfd>)関数を使用してください。

その後、各スレッドでは、sockfdを含む構造体とは異なるポインタが表示されます。スレッドが完了したら、構造体を削除して使用します。pthread_setspecific(key_to_sockfd, NULL)

スレッドが終了したら、pthread_key_delete(key_to_sockfd)に電話してストレージを削除します。 pthread_key_createにコールバック関数を提供して、スレッドが終了したときにメモリを解放することによって、自動的にクリーンアップすることもできます。

+0

これを試してみてください。 –

+0

また、Per Johanssonのコメントも考慮してください。それはより洗練されたソリューションです。 –

+0

'pthread_setspecific(key_to_sockfd、NULL)'を呼び出す必要はありません。 'int 'を' void * 'にキャストすることで、fdを値で保存することもできます。 –

2

あなたがしたいことを達成するためにグローバル変数は必要ありません。 「状態」データ構造を作成し、それを起動する前にスレッドごとに初期化します。これに対して、スレッドインターフェイスのvoid*パラメータが作成されます。

0

あなたのコードを見ると、各スレッドで上書きすると、ソケット記述子sockfdが起動します。各スレッドは新しい接続を作成し、新しいsockfdを取得します。このコードでは、あるスレッドが別のスレッドの接続を閉じる可能性があります。スレッドごとに独自のソケット記述子を使用したいのであれば、同じスレッド内で同じソケット記述子を共有するポインタを使用しないのはなぜですか?

void client_thrd(char *argv[]) 
{ 
    int sockfd; 
    set_connection(&sockfd, argv); 
    send_message(&sockfd); 
    disconnect(&sockfd); 
} 
関連する問題