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;
    }

}

为什么要这样做?

4

2 回答 2

4

您对 pthread 的使用有一些非常错误的地方。

首先,我认为您的意思是:

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

请注意以下事项:

  • pthread_create()我们正在存储in的返回值st并处理它的错误情况。
  • 我们传递的是&threadPtr[k](类型pthread_t *),而不是&threadPtr(类型pthread_t **)。这可能是您的问题的原因。

但是我对您的代码的主要问题之一是您通过传递readWriteToClientpthread_create(). 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,强调我的):

指向一种类型的函数的指针可以转换为指向另一种类型的函数的指针,然后再返回;结果应与原始指针比较。如果转换后的指针用于调用类型与引用类型不兼容的函数,则行为未定义

由于您正在调用未定义的行为,因此无法确定代码在您执行后的行为方式。

另外,请记住,将 a 转换int为 avoid *并返回并不能保证不会丢失信息(它是实现定义的),所以要小心。

如果您在启用警告的情况下进行编译,您应该在代码中看到一些其他错误,这是您应该始终做的事情。

于 2013-01-23T19:23:13.557 回答
-1

我敢打赌你的编译器会发出一些关于指针类型不兼容的警告......

我的建议是在编译阶段修复每个警告。

如果这样做了,您会注意到 pthread 函数的参数必须是指向 void 而不是 int 的指针。

另外,后一个函数必须返回一个指向 void 的指针,而不仅仅是 void ,这会导致堆栈大乱。

首先,使用连接fds数组

int connfd[MAXCON];

然后将confd保存在

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

然后,改变

pthread_create( threadPtr, NULL, readWriteToClient, connfd);

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

和改变

void readWriteToClient(int inputconnfd)

void *readWriteToClient(void *inputconnfd)

然后将其分配给局部变量

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

让我知道它是否有效

于 2013-01-23T18:43:04.030 回答