2013-01-23 7 views
0

다음 루프는 프로그램의 주요 내용입니다. 들어오는 연결을 받아들이고 스레드와 함께 작동합니다.스레드 종료, 전체 프로그램 종료?

문제는 모든 스레드가 종료 되 자마자 전체 프로그램을 종료한다는 것입니다. 코드는 다음과 같습니다.

#include <sys/socket.h> 
#include <sys/types.h> 
#include <netdb.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h> 
#include <pthread.h> 
#define BUFLEN 1500 
#define MAXCON 30 

char *returnTimeDate(int inputchoice); 
void readWriteToClient(int inputconnfd); 

int main(){ 

    int backlog = 10; 

    int fd; 
    fd = socket(AF_INET, SOCK_STREAM, 0); 
    if (fd == -1) { 
     // Error: unable to create socket 
    } 

    struct sockaddr_in cliaddr; 
    socklen_t cliaddrlen = sizeof(cliaddr); 

    struct sockaddr_in addr; 
    addr.sin_addr.s_addr = INADDR_ANY; 
    addr.sin_family = AF_INET; 
    addr.sin_port = htons(5001); 

    if (bind(fd, (struct sockaddr *) &addr, (socklen_t) sizeof(addr)) == -1) { 
     fprintf(stderr,"Bind Didn't Work\n"); 
    } 

    if (listen(fd, backlog) == -1) { 
     fprintf(stderr,"Listen Didn't Work\n"); 
    } 

    pthread_t *threadsArray = (pthread_t *)calloc(MAXCON, sizeof(pthread_t)); 
    pthread_t *threadPtr = threadsArray; 

    int k; 
    for(k = 0; k < MAXCON; k++){ 
     fprintf(stderr,"Make %d\n",k); 
     int connfd; 
     connfd = accept(fd, (struct sockaddr *) &cliaddr, &cliaddrlen); 
     if (connfd == -1) { 
      fprintf(stderr,"Accept Didn't Work\n"); 
     } 
     fprintf(stderr,"Waited\n",k); 
     pthread_create(&threadPtr, NULL, readWriteToClient, (void *)connfd); 
     threadPtr++; 
    } 

    pthread_t *threadPtrJoin = threadsArray; 

    for(k = 0; k < MAXCON; k++){ 
     fprintf(stderr,"Join %d\n",k); 
     pthread_join(*threadPtrJoin, NULL); 
     threadPtrJoin++; 
    } 

/* readWriteToClient(connfd);*/ 

    close(fd); 

    return 0; 

} 

void readWriteToClient(int inputconnfd){ 

    int connfd = inputconnfd; 

    while(1){ 

     char *dateString = "DATE\r\n"; 
     char *timeString = "TIME\r\n"; 
     char *endString = "end"; 

     char *bufferTime = returnTimeDate(0); 
     char *bufferDate = returnTimeDate(1); 

     ssize_t i; 
     ssize_t rcount; 
     char buf[BUFLEN]; 
     char *toReturn = (char *)malloc(BUFLEN*sizeof(char)); 
     rcount = read(connfd, buf, BUFLEN); 
     if((strcmp (buf, dateString)) == 0){ 
      strcpy(toReturn, bufferDate); 
     } 
     if((strcmp (buf, timeString)) == 0){ 
      strcpy(toReturn, bufferTime); 
     } 
     if((strcmp (buf, endString)) == 0){ 
      goto outside; 
     } 
     if (rcount == -1) { 
      // Error has occurred 
      printf("Error: rcount -1"); 
     } 

/*  fprintf(stderr,"I have received = %s\n",buf);*/ 

     if (write(connfd, toReturn, BUFLEN) == -1) { 
      fprintf(stderr,"I didn't write = %s\n",buf);  
     } 
    } 

    outside: return; 

} 

char *returnTimeDate(int inputchoice){ 

    time_t timer; 
    char *bufferTimee = (char *)malloc(25*sizeof(char)); 
    char *bufferDatee = (char *)malloc(25*sizeof(char)); 
    struct tm* tm_info; 
    time(&timer); 
    tm_info = localtime(&timer); 
    strftime(bufferTimee, 25, "%H:%M:%S\n\0", tm_info); 
    strftime(bufferDatee, 25, "%d:%m:%Y\n\0", tm_info); 

    if(inputchoice == 0){ 
     return bufferTimee; 
    }else{ 
     return bufferDatee; 
    } 

} 

왜 이렇게할까요?

+1

메서드의 코드가 실행되는지 확인 했습니까? 나는 비 - 보이드 * 스레드 방법을 본 적이 없다. –

+0

예, 스레드는 매력처럼 작동하고, 주 프로그램 만 종료됩니다. 호기심에서 당신이 언급 한 표준 대회는 무엇입니까? –

+1

스레드를 만든 후 무엇을하고 있습니까? – imreal

답변

4

이 몇 가지 있습니다 작동하는지 알려주세요 다음

void *readWriteToClient(void *inputconnfd) 

void readWriteToClient(int inputconnfd) 

int connfd = *((int *) inputconnfd); 

와 지역 변수에 할당 변경 그게 당신 pthreads의 사용에 매우 잘못되었습니다. 모든

첫째, 난 당신이 의미 생각 : 우리는 stpthread_create()의 반환 값을 저장하고

  • 과 오류 사건을 처리 :

    int st = pthread_create(&threadPtr[k], NULL, readWriteToClient, (void *)connfd); 
    if (st != 0) { 
        /* handle error */ 
    } 
    

    참고 다음.

  • &threadPtr (pthread_t **)이 아닌 &threadPtr[k] (유형이 pthread_t *)입니다. 이것은 문제의 원인 일 가능성이 큽니다.

하지만 난 당신의 코드를 가지고있는 주요 문제 중 하나, 당신은 pthread_create()readWriteToClient를 전달하여 정의되지 않은 동작을 호출 할 것입니다.pthread_create 프로토 타입은 다음과 같다 :

int pthread_create(pthread_t *restrict, 
        const pthread_attr_t *restrict, 
        void *(*start_routine)(void*), 
        void *restrict arg); 

당신이 &threadPtr&threadPtr[k]로 변경하더라도, 당신은 다음과 같이 호출 할 것 :

int pthread_create(pthread_t *restrict, 
        const pthread_attr_t *restrict, 
        void (*start_routine)(int),  // oops! 
        void *restrict arg); 

그래서는 pthread_create() 하나의 함수에 대한 포인터를 받아 들인다 다른 유형의 함수 (C11, 6.7.6.3/15, 강조 광산)에 대한 포인터를 전달하고 있습니다 :

두 가지 재미를 위해 호환 될 수있는 형식이면 호환 가능한 반환 형식을 지정해야합니다. 또한 매개 변수 유형 목록이 둘 다 존재하는 경우 매개 변수 수와 줄임표 종료 문자 사용시 동의해야합니다. 해당 매개 변수는 호환 유형이어야합니다. [...]

함수에 대한 포인터는 암시 적으로 변환되고, 함수 어쨌든라고하지만,이 표준 (C11, 6.3.2.3/8 강조 광산)에 따라, 불법 :

한 유형의 함수에 대한 포인터가 다른 유형의 함수에 대한 포인터로 변환 될 수 있습니다. 결과는 과 원래 포인터를 비교해야합니다. 형식이 참조 된 형식과 호환되지 않는 함수를 호출하는 데 변환 포인터를 사용하는 경우 동작은 정의되지 않음입니다.

정의되지 않은 동작을 호출하기 때문에 코드를 실행 한 후에 코드가 어떻게 동작하는지 알 수 없습니다.

또한 intvoid *으로 변환 한 다음 정보를 잃지 않고 (구현 정의 됨) 보장 할 수 없으므로주의해야합니다.

경고가 컴파일 된 상태에서 컴파일해야하는 코드에는 몇 가지 다른 오류가 있습니다. 즉, 은 항상이어야합니다.

-1

나는

나의 제안은 컴파일 단계에서 매주 경고를 해결하려면 입니다 .... 컴파일러가 호환되지 않는 포인터 유형에 대한 몇 가지 경고 yelding이었다 내기.

이 작업을 수행했다면 pthread 함수의 매개 변수는 int가 아니라 void에 대한 포인터 여야합니다.

게다가 후자의 함수는 스택에 큰 혼란을 가져올 수있는 void가 아닌 void에 대한 포인터를 반환해야합니다.

먼저 변경하고 다음

connfd[k] = accept(fd, (struct sockaddr *) &cliaddr, &cliaddrlen); 

에 connfd 저장

int connfd[MAXCON]; 

FDS 연결 배열을 사용

pthread_create(threadPtr, NULL, readWriteToClient, connfd); 

pthread_create(threadPtr, NULL, readWriteToClient, (void *) &connfd[k]); 

하고

+0

왜 안 int connfd = (int) inputconnfd;'? –

+0

내 고정 버전에 따르면 inputconnfd가 이제는 잘못된 조언과 위험한 조언을 위해 void –

+1

-1에 대한 포인터이기 때문입니다. 강력한 동기화를 추가하지 않는다면'pthread_create (threadPtr, NULL, readWriteToClient, (void *) & connfd);는 ** 유효하지 않습니다 ** (그렇게했다면'(void *)'로의 캐스트는 불필요하고 중복됩니다) 새 스레드가 변경되거나 범위를 벗어나기 전에 값을 읽는지 확인합니다. 대부분의 경우'connfd'를 값으로 전달하는 것이 바람직하지만'(void *)'로 형변환해야합니다. –