2011-09-14 9 views
0

다음과 같은 클라이언트 프로그램이 있으며이를 다중 스레드, 즉 연결 당 하나의 스레드로 만들어야합니다. 그러나 변수 sockfd는 하나의 스레드에 대해 전역으로 유지되어야합니다. 나는 이것을하기 위해 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; 
} 

하나의 스레드에 대해 프로그램을 실행 했으므로 정상적으로 작동합니다. 그러나 스레드 수를 늘리면 글로벌 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); 
} 
관련 문제