Розетки с выпуском pthreads - PullRequest
       8

Розетки с выпуском pthreads

0 голосов
/ 15 сентября 2011

Я создаю серверную / клиентскую эхо-программу.Клиент читает строку, отправляет на сервер, а сервер отправляет строку обратно клиенту.

Структуры данных:

typedef struct writeStruct
{
    FILE *wsock;
    int sockfd;
} writeStruct;

typedef struct readStruct
{
    FILE *rsock;
    int sockfd;
 } readStruct;

Часть основной функции:

main()
{
    writeStruct *writeData;
    readStruct *readData;
    writeData = malloc(sizeof(writeData));
    readData = malloc(sizeof(readData));

    pthread_t write;
    pthread_t read;

    FILE *rsock, *wsock;

    int sockfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    rsock = fdopen(sockfd, "r");
    wsock = fdopen(sockfd, "w");

    writeData->wsock = wsock;
    readData->rsock = rsock;

    writeData->sockfd = sockfd;
    readData->sockfd = sockfd;

    pthread_create(&write, NULL, writeProcess, (void*)writeData);
    pthread_create(&read, NULL, readProcess, (void*)readData);

    pthread_join(write, NULL);
    pthread_join(read, NULL);
 }

И функции:

Функция записи:

void *writeProcess(void *writeData)
{
    FILE *wsock = ((writeStruct*)writeData)->wsock;
    int sockfd = ((writeStruct*)writeData)->sockfd;
    int success = 0;
    char *buf = malloc(sizeof(char) * MAXDATASIZE);

    while(fgets(buf, MAXDATASIZE, stdin) != NULL)
    {
        fputs(buf, wsock);
        fflush(wsock);
    }
    fputs(buf, wsock);
    free(buf);
    shutdown(sockfd, SHUT_WR);
}

Функция чтения:

void *readProcess(void *readData)
{
    FILE *rsock = ((readStruct*)readData)->rsock;
    int sockfd = ((readStruct*)readData)->sockfd;
    char *rcv, *rcvAux;
    rcv = malloc(sizeof(char) * MAXDATASIZE);
    rcvAux = malloc(sizeof(char) * MAXDATASIZE);

    rcvAux = fgets(rcv, MAXDATASIZE, rsock);
    while(rcvAux != NULL)
    {
        fflush(rsock);
        numCharsRcv += strlen(rcv);
        numLinesRcv++;
        printf("%s", rcv);
        rcvAux = fgets(rcv, MAXDATASIZE, rsock);
    }
    printf("%s", rcv);
    free(rcv);
}

Бывает, что writeProcess () работает нормально, но readProcess ()нет, очевидно, rsock получает неверный адрес памяти, и я получаю ошибку сегментации.


Извините, я пропустил некоторые части кода, это было бы очень долго.

На самом делеЯ подключаю сокет и функция записи работает, но когда он входит в функцию чтения, указатель файла теряет свою ссылку, по крайней мере, я видел это при отладке с помощью GDB.

Эта проблема имеетначал происходить сразу после того, как я добавил потоки, когда он работал на одном процессе, он работал просто отлично

Ответы [ 3 ]

4 голосов
/ 15 сентября 2011
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);

Вышеуказанное создает отключенный TCP-сокет.

rsock = fdopen(sockfd, "r");
wsock = fdopen(sockfd, "w");

Они открывают ту же разъединенную розетку, что и две неисправные FILE*.

Для начала вам понадобятся два разных подключенных разъема.

Если код, который вы разместили, представляет собой законченную программу, я не вижу, как она должна работать. И читатель, и писатель начинают с fgets(), который должен навсегда их блокировать, поскольку данных не будет.

1 голос
/ 15 сентября 2011

Точка 1 ниже, вероятно, будет реальной причиной вашей ошибки сегментации:

  1. fgets добавляет нулевой символ в конец сохраненной строки. Это означает, что вы должны передать MAXDATASIZE-1 вместо MAXDATASIZE, в противном случае может произойти переполнение.

  2. Некоторые могут утверждать, что у вашей программы есть утечка памяти, потому что вы присваиваете возврат fgets для rcvAux, который сам указывал на другой адрес памяти, который вы выделили вручную. После этого назначения вы не сможете free это, потому что адрес этой выделенной памяти потерян.

  3. Вы не проверяете возвращаемые значения для socket() и fdopen(). И вы не закрываете sockfd до выхода из приложения.

Обновление

Как указано R .. в комментариях, использование fflush для не записываемого дескриптора файла является неопределенным поведением.

Ваш фрагмент кода не показывает ни connect(), ни bind() + listen() + accept(). Ваш сокет должен быть сначала подключен для выполнения операций чтения и / или записи. Проверка возвращаемых значений каждой операции поймала бы это.

0 голосов
/ 15 сентября 2011

Я бы начал с проверки, возвращают ли fdopen () правильные значения, и, если нет, залог.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...