Как извлечь подстроку из сообщения POSIX?

#c #posix #message-queue

#c #posix #очередь сообщений

Вопрос:

У меня есть серверно-клиентская программа, клиент отправляет серверу сообщение, используя a struct , которое имеет три основных значения: дату и две временные метки.

Теперь, когда сервер получает сообщение, я пытаюсь извлечь дату из структуры сообщения в качестве подстроки массива символов, а затем преобразовать ее в int, но я застрял на несколько часов, даже пытаясь получить соответствующие символы из сообщения.

Моя серверная программа:

 #include "msg.h"

const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

void delete_mq(char* mname, mqd_t qid) {
    if (mq_close(qid) < 0) {
        perror("Error closing queue");
        exit(1);
    }
    if (mq_unlink(mname) < 0) {
        perror("Error unlinking queue");
        exit(1);
    }
}

void make_command(MESSAGE *mess, char *mname, mqd_t qid) {
    printf("making command, hehen");
    if (strcmp(mess->date,"STOP") == 0){
            printf("Stopping the server.n");
            delete_mq(mname, qid);
            exit(0);
    }

    // this is where I am stuck
    char thedate[3];
    char *date = mess->date;
    strncpy(thedate, date 1, 1);
    thedate[2] = '';
    printf("%sn", thedate);
    
    strcpy(mess->messtext,"Some text respone message");
}

int main(int argc, char** argv)
{
    int flagsc = O_RDONLY | O_CREAT;
    mode_t mode = 0600;

    struct mq_attr attr;
    attr.mq_flags = 0;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = sizeof(MESSAGE);
    attr.mq_curmsgs = 0;
    
    int flags = O_WRONLY;
    char cname[10];
    char sqname[15];
    sprintf(sqname,"%s%s",qname,getlogin());

    mqd_t qid = mq_open(sqname, flagsc, mode, amp;attr);

    if (qid <0) {
        perror("Error opening message queue");
        exit(1);
    }

    for (;;) {
        MESSAGE message;
        unsigned int priority = 0;

        if (mq_receive(qid, (char*) amp;message, sizeof(message), amp;priority) != -1) {
            make_command(amp;message, qname, qid);
            sprintf(cname,"/%d", message.pid);
            message.pid = getpid();
            mqd_t cmqid = mq_open(cname, flags);
            mq_send(cmqid, (char*)amp;message, sizeof(MESSAGE), 0);
            mq_close(cmqid);
        }
    }

    mq_close(qid);
    return 0;
}
 

Моя клиентская программа:

 // ./client 11.23. 13:24 16:43
#include "msg.h"

int main(int argc, char** argv)
{
    if (argc != 4){
        printf("Usage: ./client <date e.g. 11.23.> <time1 e.g. 13:24> <time2 e.g. 16:43>n");
        exit(1);
    }

    int flags = O_WRONLY;
    int cflags = O_RDONLY|O_CREAT;
    mode_t mode = 0600;
    char sqname[15];
    sprintf(sqname,"%s%s", qname, getlogin());
    mqd_t qid = mq_open(sqname, flags);

    if (qid == -1) {
        perror("Error opening queue in client");
        exit(1);
    }

    struct mq_attr temp;

    if (mq_getattr(qid, amp;temp) == -1) {
        perror("Error with getattr in client");
    } else {
         // finish later
    }

    char cqname[20];

    struct mq_attr attr;
    attr.mq_flags = 0;
    attr.mq_maxmsg = 8;
    attr.mq_msgsize = sizeof(MESSAGE);
    attr.mq_curmsgs = 0;

    sprintf(cqname,"/%d", getpid());
    mqd_t cqid = mq_open(cqname, cflags, mode, amp;attr);

    if (cqid == -1) {
        perror("Error opening queue in client");
        exit(1);
    }

    MESSAGE mess;
    strcat(mess.date, argv[1]);
    strcat(mess.time1, argv[2]);
    strcat(mess.time2, argv[3]);

    mess.pid = getpid();

    printf("Client has sent request");

    if (mq_send(qid, (char*) amp;mess, sizeof(MESSAGE), 0) < 0) {
        perror("Error sending message in client");
        exit(1);
    }

    if (strcmp(mess.date,"STOP") != 0) {
        if (mq_receive(cqid,(char*) amp;mess, sizeof(MESSAGE), 0) < 0) {
            perror("Error receiving message in client");
            exit(1);
        }
    } else {
        printf("Stopping the client.n");

        if(mq_close(qid) < 0) {
            perror("error closing server queue");
            exit(1);
        }

        if(mq_close(cqid) < 0) {
            perror("error closing client queue");
            exit(1);
        }

        if (mq_unlink(cqname) < 0) {
            perror("Error unlinking client queue");
            exit(1);
        }
        exit(0);
    }

    printf("%sn", mess.messtext);

    if(mq_close(qid) < 0) {
            perror("error closing server queue");
            exit(1);
    }

    if(mq_close(cqid) < 0) {
        perror("error closing client queue");
        exit(1);
    }

    if (mq_unlink(cqname) < 0) {
        perror("Error unlinking client queue");
        exit(1);
    }
    
    exit(0);
}
 

И заголовок:

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <mqueue.h>

#define KEY 1111

typedef struct{ 
    int pid;
    // e.g. 11.23.
    char date[50];
    char time1[50];
    char time2[50];
    char messtext[10];  
} MESSAGE;

char * qname="/server_";
 

Теперь аргументами для выполнения клиента должны быть дата и две временные метки. Когда сервер получает сообщение, я хочу извлечь первые два символа из date (месяца) и преобразовать его в int , чтобы я мог получить соответствующий месяц *months[] .

Я перепробовал почти все: strcpy , memcpy , sprintf и я схожу с ума, потому что он либо напечатает только первое число месяца, либо неправильно преобразует, либо печатает дополнительные сумасшедшие символы из памяти, и я едва начал разбивать сообщение на части. По mess->date -видимому, в его первой позиции есть какой-то другой символ, и я не могу его пропустить.

Может ли кто-нибудь помочь мне достичь того, что я описал?

Комментарии:

1. atoi cplusplus.com/reference/cstdlib/atoi

2. Я пробовал atoi , я знаю, для чего это нужно, но я даже не могу дойти до того момента, когда мне придется его использовать. Я не могу извлечь месяц из массива символов.

3. strncpy(thedate, date 1, 1) означает скопировать 1 символ из строки, начинающейся с date 1 to thedate . Итак, если date это строка «Jan 20», вы бы прочитали a в «Jan» только потому date 1 , что это строка «an 20», и вы копируете только 1 символ. Я подозреваю, что вам может понадобиться strncpy(thedate, date, 3) , если вы читаете названия месяцев, такие как «Январь», «Февраль» и т.д. Также имейте в виду, что thedate это не будет завершаться нулевым значением из-за вашего объявления char thedate[3]; , которое ограничивает вас такими функциями, как strncpy/memcpy и strncmp/memcmp которые требуют параметра, указывающего максимальное количество символов для проверки.

4. Нет, date это строка «11.23.», Но когда я ее печатаю, в первой позиции появляется дополнительный символ, поэтому я попытался strncpy(thedate, date 1, 2) , но это тоже не работает, по какой-то причине он не копируется 11 thedate . Также обратите внимание, что я завершил thedate с '' помощью .

5. MESSAGE mess; в вашем клиентском коде объявляется mess без инициализатора, поэтому strcat(mess.date, argv[1]); можно добавить строку «11.23.» к неинициализированным / мусорным данным. Вы можете исправить эту ошибку, используя MESSAGE mess = { -1 }; для инициализации pid поля недопустимый PID. Остальные данные в структуре будут инициализированы нулями и strcat будут работать так, как ожидалось. Возможно, это не полное решение, но это начало.