Как бы я пошел об отправке битовых полей через сокет? - PullRequest
1 голос
/ 25 мая 2011

Мне нужно отправить набор битовых полей вместе со строкой символов от клиента на сервер.

Итак, у меня есть:

#define YES 1
#define FLAG 2
int main(int argc, char* argv[])
{
    return sendToServer("The Message", YES | FLAG);
}
int sendToServer(char* msg, int bitfields)
{
   /* create socket and connect to server */
   /* Assume sock is set */
   send(sock, msg, strlen(msg), 0);
   return 0;
}

Что было бы лучшеспособ отправки битовых полей?Есть ли способ отправить битовые поля вместе со строкой?

РЕДАКТИРОВАТЬ: Хорошо, я пытаюсь реализовать метод Влада.Мой клиент в значительной степени идентичен тому, что он написал.Я поставил флаг в начале data [0], и вместо bswap я использовал htonl.Мой сервер:

int main(int argc, char* argv[])
{
    /* create socket and wait for connection */
    char buffer[BUFFERSIZE];
    size_t rcvdB = recv(clntSock, buffer, sizeof(int),0);
    int flags = ntohl((int) buffer);
    rcvdB = recv(clntSock, buffer, sizeof(size_t),0);
    size_t msgSize = ntohl((size_t) buffer);
    rcvdB = recv(clntSock,buffer,msgSize,0);
    /* Then I send back to the client */
    ssize_t sntB = send(clntSock,buffer,msgSize,0);
}

Когда клиент печатает сообщение, в конце сообщения есть несколько символов ascii.

EDIT2:

Проблема возникает, когдаЯ прочитал более 8 байтов данных

Ответы [ 4 ]

2 голосов
/ 25 мая 2011

Как уже отмечали другие, это зависит от протокола.Я бы использовал что-то вроде этого:

int sendToServer(char* msg, int bitfields)
{
   unsigned int bits = bswap32 (bitfields); // Convert host to network byte order.

   size_t len = strlen (msg);   // Calculate string length.
   size_t nlen = bswap64 (len); // Convert length's byte order from host to network.

   iovec data[3]; // Prepare 3 I/O buffers to send data by performing a single system call (they are expensive).

   // Send length of the string first.
   data[0].iov_base = &nlen;
   data[0].iov_len = sizeof (nlen);

   // Send string...
   data[1].iov_base = msg;
   data[1].iov_len = len;

   // And, of course, send bits.
   data[2].iov_base = &bits;
   data[2].iov_len = sizeof (bits);

   // Write all of those to the socket.
   writev (fd, &data, sizeof (data) / sizeof (data[0]));
}

На принимающей стороне вы можете прочитать первые sizeof (size_t) байты, преобразовать из сети в порядок байтов хоста, привести к size_t.Это скажет вам длину строки.Затем прочитайте буфер этой длины - это будет ваша строка.Наконец, прочитайте еще sizeof (int) байт - это будет ваше битовое поле.

См. Также:

2 голосов
/ 25 мая 2011

Конечно, это зависит от вашего сетевого протокола. Если вы разрабатываете его, и у вас есть максимум 8 флагов для отправки, поместите их в первый байт сообщения. Если у вас есть максимум 16, но их в первых двух байтах и ​​т. Д.

int sendToServer(int sock, char* msg, int flags)
{
    size_t siz = strlen(msg) + 1;  // +1 for NUL
    unsigned char *buf = malloc_or_die(siz + 1);
    buf[0] = flags;
    memcpy(buf + 1, msg, size);

    send(sock, msg, strlen(msg), 0);

    free(buf);
    return 0;
}

(я изменил bitfields на flags, поскольку это то, что они есть. Битовое поле - это набор флагов.)

1 голос
/ 25 мая 2011

Вероятно, лучше всего отправлять битовые поля в виде байтов для необработанного int (например, send(sock, &bitfields, sizeof(bitfields), 0)), убедившись, что размер и порядковый номер одинаковы для клиента и сервера.Вероятно, было бы проще отправить биты перед строкой, поскольку сервер мог бы легко извлечь строку после фиксированного числа байтов.

0 голосов
/ 25 мая 2011

Битовое поле образует число, например, 1|2 дает 3, поскольку %01 | %10 = %11.

Так что все, что вам нужно отправить, это этот номер. Вид

snprintf(buffer, buffer_size, "%s-%d", message, number);
send(sockfd, buffer, buffer_size, 0);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...