Передача символов из структур через сокеты в c - PullRequest
0 голосов
/ 26 сентября 2018

Я пытаюсь отправлять / получать сообщения между моим сервером и клиентом.В настоящее время у меня есть сервер на моем сервере, который содержит значение char.Я пытаюсь передать это значение моему клиенту.См. Следующее:

tileInfo->tiles[user_cords_x][user_cords_y].identifier = '+'; // Char i want to pass
write_client_msg(cli_sockfd, &tileInfo->tiles[user_cords_x][user_cords_y].identifier);

/* Writes a message to a client socket. */
void write_client_msg(int cli_sockfd, char * msg)
{
    int n = write(cli_sockfd, msg, strlen(msg));
    if (n < 0)
        error("ERROR writing msg to client socket");

}

На моей стороне клиента я получаю следующее:

char *msg;
char identity = read(sockfd, msg, 1);
printf("This is the value: %d \n", identity);

В настоящее время вывод, который я получаю, This is the value: 1.Я новичок в сокетах и ​​не полностью понимаю прохождение символов.Может ли кто-нибудь объяснить и показать, как передать знак «+» моей стороне клиента?

Ответы [ 3 ]

0 голосов
/ 26 сентября 2018

Правильное решение (на основе вашего кода) будет:

char *msg;
msg = malloc(2);
if (read(sockfd, msg, 1)!=1) {
    printf("Something wrong\n");
    return 0;
}
msg[1]= '\0';
printf("Sent received: %s \n", msg);
0 голосов
/ 26 сентября 2018

Вы делаете несколько ошибок с вашим кодом.

На стороне сервера, в этом коде:

write_client_msg(cli_sockfd, &tileInfo->tiles[user_cords_x][user_cords_y].identifier);

Понятно, что identifier является единственным char,иначе код не скомпилируется.В этом случае использование strlen() внутри write_client_msg() неверно, поскольку msg не будет иметь нулевого терминатора при передаче указателя на один char.В конечном итоге вы могли бы передать мусор другой стороне, если бы не просто сбой при обращении к недействительной памяти.

Затем на стороне клиента вы передаете неинициализированный указатель msg на read().Но вы также отображаете возвращаемое значение read(), которое является фактически полученным байтом.Вот почему на вашем дисплее отображается 1, поскольку вы запрашиваете 1 байт для получения.

Для правильной отправки и получения identifier вам понадобится что-то более похожее на это:

void write_client_msg(int sockfd, char *msg, size_t msg_len)
{
    int n = write(sockfd, msg, msg_len);
    if (n < 0)
        error("ERROR writing msg to client socket");
}

...

write_client_msg(cli_sockfd, &tileInfo->tiles[user_cords_x][user_cords_y].identifier, 1);

char identity;
int n = read(sockfd, &identity, 1);
if (n < 0)
    error("ERROR reading identity from client socket");
else if (n == 0)
    error("DISCONNECTED while reading identity from client socket");
else
    printf("This is the value: %c \n", identity);

Как говорится, лучшее решение - write_client_msg() отправить msg_len перед отправкой msg.Тем более, что write_client_msg() не знает, какие данные он отправляет.Затем клиент может прочитать msg_len, чтобы узнать, сколько байтов нужно прочитать для msg, а затем обработать msg при необходимости.

Кроме того, write() и read() могут вернуть меньшебайт, чем запрошено, поэтому вам нужно вызывать их в циклах, чтобы убедиться, что вы действительно отправляете / получаете все.

Например:

int write_all(int sockfd, void *data, size_t data_len)
{
    char *d = (char*) data;
    while (data_len > 0)
    {
        int n = write(sockfd, d, data_len);
        if (n < 0)
            return n;
        d += n;
        data_len -= n;
    }
    return 1;
}

void write_client_msg(int sockfd, char *msg, size_t msg_len)
{
    uint32_t len = htonl(msg_len);
    int n = write_all(sockfd, &len, sizeof(len));
    if (n == 1)
        n = write_all(sockfd, msg, msg_len);
    if (n < 0)
        error("ERROR writing msg to client socket");
}

...

write_client_msg(cli_sockfd, &tileInfo->tiles[user_cords_x][user_cords_y].identifier, 1);

int read_all(int sockfd, void *data, size_t data_len)
{
    char *d = (char*) data;
    while (data_len > 0)
    {
        int n = read(sockfd, d, data_len);
        if (n <= 0)
            return n;
        d += n;
        data_len -= n;
    }
    return 1;
}

char *read_server_msg(int sockfd)
{
    uint32_t len;
    int n = read_all(sockfd, &len, sizeof(len));
    if (n <= 0)
        return NULL;
    len = ntohl(len);
    char *msg = malloc(len+1);
    if (!msg)
        return NULL;
    n = read_all(sockfd, msg, len);
    if (n <= 0) {
        free(msg);
        return NULL;
    }
    msg[len] = '\0';
    return msg;
}

...

char *msg = read_server_msg(sockfd);
if (!msg)
    error("ERROR reading msg from client socket");
else {
    printf("This is the value: %s \n", msg);
    free(msg);
}
0 голосов
/ 26 сентября 2018

Решено:

char *msg;
msg = (char*) malloc (1);
read(sockfd, msg, 1);
printf("Sent received: %s \n", msg);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...