2017-06-13 25 views
0

我正在寫一個簡單的代碼來測試線程池。我有一個客戶端通過不同的端口發送數據到服務器。有些線程接收數據,然後將它們發送到其他線程進行處理。 現在,我所做的唯一處理就是將數據寫入文件。C程序調試時只寫入文件

這是工作者線程的代碼。

void* worker_thread(void* arg){ 
    int i, workerNum; 
    pthread_t worker_id = pthread_self(); 
    char *ticket = (char*) arg; 
    char dumpfile[50]; 
    for(i=0;i<10;i++) 
     if(pthread_equal(worker_id, id_pool[i])) 
     break; 
    if(10==i){ 
     pthread_exit(NULL); 
    } 
    workerNum = i; 
    fprintf(stdout, "Worker [%d] busy\n",workerNum); 
    sprintf(dumpfile, "worker_%d.log",workerNum); 
    if(strlen(ticket)<4){ 
     fprintf(stdout, "Worker [%d] RELEASED!!\n",workerNum);  
     poolStatus[workerNum] = 0; 
     pthread_mutex_unlock(&mutexes[workerNum]); 
     pthread_exit(NULL); 
    } 
    FILE *logFile = fopen(dumpfile, "a+"); 
    // ticket[strlen(ticket)] 
    fprintf(logFile, "%s\n", ticket); 
    fclose(logFile); 
    sleep(workerNum+2); 
    poolStatus[workerNum] = 0; 
    fprintf(stdout, "Worker [%d] RELEASED!!\n",workerNum); 
    pthread_mutex_unlock(&mutexes[workerNum]); 
    pthread_exit(NULL); 
} 

當我運行一個調試器(GDB,在linux下)時,代碼工作。當我只是在命令行上運行它時,它會運行但不會創建文件! 你能幫忙嗎?

的完整代碼:

#include <time.h> 
#include <errno.h> 
#include <netdb.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <pthread.h> 
#include <strings.h> 
#include <sys/time.h> 
#include <arpa/inet.h> 
#include <sys/ioctl.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <sys/socket.h> 

#define BUFSIZE  65535 
#define NUMWORKERS 10 

static pthread_mutex_t mutexes[NUMWORKERS]; 
pthread_t id_pool[NUMWORKERS], id_servers[6]; 
int serverports[6]   = {22191, 22192, 22193, 7525, 7526, 7527}; 
char poolStatus[NUMWORKERS] = {0}; 

void error(char *msg) { 
    FILE *logFile = fopen("errorlog.log", "a+"); 
    fprintf(logFile, "%s\n", msg); 
    fclose(logFile); 
    exit(1); 
} 

void* serverListener(void* arg); 
void* worker_thread(void* arg); 


int main(){ 
    int i, t_err[6]; 
    for(i=0; i< NUMWORKERS; i++) 
     pthread_mutex_init(&mutexes[i],NULL); 
    for(i=0; i<6; i++){ 
     t_err[i] = pthread_create(&id_servers[i], NULL, serverListener, NULL); 
    } 
    pthread_join(id_servers[5], NULL); 
    return 0; 
} 


void* serverListener(void* arg){ 
    int    parentfd, childfd;  // parent socket & child socket 
    int    portno, clientlen;  // port number and size of client address 
    struct sockaddr_in serveraddr; 
    struct sockaddr_in clientaddr;// server and client addresses 
    struct hostent  *hostp;    // client host info 
    char    buf[BUFSIZE];   // message buffer 
    char    *hostaddrp;   // dotted decimal host addr string 
    int    optval, n;    // flag value for setsockopt and message byte size 
    unsigned int  CLOCKREF, CLOCKCOUNT; 
    pthread_t   id = pthread_self(); // own thread id 
    int    threadNumber, i=0;  // thread number linked to ort to listen to. 
    char    dumpfile[50]; 
    for(i=0; i<6; i++) if(pthread_equal(id, id_servers[i])) break; 
    threadNumber = i; 

    portno = serverports[threadNumber]; 
    sprintf(dumpfile, "receiver_%d.log",portno); 
    // socket: create the parent socket 
    parentfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (parentfd < 0) 
     error("ERROR opening socket"); 

    optval = 1; 
    setsockopt(parentfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int)); 

    // build the server's Internet address 
    bzero((char *) &serveraddr, sizeof(serveraddr)); 
    serveraddr.sin_family = AF_INET; 

    // let the system figure out our IP address 
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); 

    // this is the port we will listen on 
    serveraddr.sin_port = htons((unsigned short)portno); 

    // bind: associate the parent socket with a port 
    if (bind(parentfd, (struct sockaddr *) &serveraddr, 
     sizeof(serveraddr)) < 0) 
     error("ERROR on binding"); 

    // listen: make this socket ready to accept connection requests 
    if (listen(parentfd, 5) < 0) /* allow 5 requests to queue up */ 
     error("ERROR on listen"); 

    // main loop: wait for a connection request 
    clientlen = sizeof(clientaddr); 
    while (1) { 
     // accept: wait for a connection request 
     childfd = accept(parentfd, (struct sockaddr *) &clientaddr, &clientlen); 
     if (childfd < 0) 
     error("ERROR on accept"); 

     // gethostbyaddr: determine who sent the message 
     hostp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr, 
       sizeof(clientaddr.sin_addr.s_addr), AF_INET); 
     if (hostp == NULL) 
     error("ERROR on gethostbyaddr"); 
     hostaddrp = inet_ntoa(clientaddr.sin_addr); 
     if (hostaddrp == NULL) 
     error("ERROR on inet_ntoa\n"); 
     fprintf(stdout, "server established connection with %s (%s)\n", hostp->h_name, hostaddrp); 

     // read: read input string from the client 
     CLOCKREF = (unsigned int)time(NULL); 
     int counter = 0; 
     while(1){ 
      CLOCKCOUNT = (unsigned int)time(NULL) - CLOCKREF; 
      bzero(buf, BUFSIZE); 
      n = read(childfd, buf, BUFSIZE); 
      if (n < 0)  error("ERROR reading from socket"); 
      if(0==n) counter++; 
      if(3<=counter) { 
       close(childfd); 
       return; 
      } 

      int busyWorker = 1; 
      i = 0; 
      while(busyWorker){ 
       if(i>=NUMWORKERS) i = 0; 

       if(pthread_mutex_trylock(&mutexes[i])==0){ // not locked, can be used 
        fprintf(stdout, "port [%d] sends to thread [%d]\n", portno, i); 
        pthread_create(&id_pool[i], NULL, worker_thread, (void*)buf); 
        busyWorker = 0; 
        break; 
       } 
       i++; 
      } 
     } 
     close(childfd); 
    } 
} 

void* worker_thread(void* arg){ 
    int i, workerNum; 
    pthread_t worker_id = pthread_self(); 
    char *ticket = (char*) arg; 
    char dumpfile[50]; 
    for(i=0;i<10;i++) 
     if(pthread_equal(worker_id, id_pool[i])) 
     break; 
    if(10==i){ 
     pthread_exit(NULL); 
    } 
    workerNum = i; 
    fprintf(stdout, "Worker [%d] busy\n",workerNum); 
    sprintf(dumpfile, "worker_%d.log",workerNum); 
    if(strlen(ticket)<4){ 
     fprintf(stdout, "Worker [%d] RELEASED!!\n",workerNum);  
     poolStatus[workerNum] = 0; 
     pthread_mutex_unlock(&mutexes[workerNum]); 
     pthread_exit(NULL); 
    } 
    FILE *logFile = fopen(dumpfile, "a+"); 
    // ticket[strlen(ticket)] 
    fprintf(logFile, "%s\n", ticket); 
    fclose(logFile); 
    sleep(workerNum+2); 
    poolStatus[workerNum] = 0; 
    fprintf(stdout, "Worker [%d] RELEASED!!\n",workerNum); 
    pthread_mutex_unlock(&mutexes[workerNum]); 
    pthread_exit(NULL); 
} 
+0

你在標準輸出中看到「工作[%d]忙\ n」嗎? –

+0

是的!發送到標準輸出的所有消息都打印好了 – PhoenixBlue

+0

你怎麼稱之爲'worker_thread'?你的問題缺乏很多可能會提出問題的代碼。 –

回答

0

我相信我已經找到了問題!

要將serverListener線程中的消息傳遞給worker_thread,我使用指向緩衝區的指針來讀取套接字。問題是,在worker_thread可以處理它之前,serverListener已將該值重置爲零(bzero(buf, BUFSIZE))!並且考慮到worker_thread只能在大於4時寫入文件的事實,它不會寫入文件。 所以要解決我的問題,我更換了行:

pthread_create(&id_pool[i], NULL, worker_thread, (void*)buf); 

由:

char *msg2send = strdup(buf); 
pthread_create(&id_pool[i], NULL, worker_thread, (void*)msg2send); 

而且它的伎倆! 仍然沒有真正解釋爲什麼它可以在調試模式下創建文件...