Pergunta

Para uma aplicação em rede, o caminho que temos vindo a transmissão de dados dinâmica é através memcpying um struct em um (* void). Isto coloca alguns problemas, como quando isso é feito para um std :: string. Strings podem ser de comprimento dinâmico, assim como será o outro lado sabe quando as extremidades da corda? Uma idéia que eu tinha era usar algo semelhante ao de Java DataOuputStream, onde eu poderia simplesmente passar quaisquer variáveis ??para ele e ele poderia, então, ser colocado em um (* void). Se isso não puder ser feito, então é legal. Eu só não gosto muito memcpying um struct. Algo sobre ele não parece muito certo.

Obrigado,
Robbie

Foi útil?

Solução

nada de errado com memcpy em um struct - como GNL como a estrutura é preenchido com buffers de tamanho fixo. Coloque uma variável dinâmica lá e você tem que serialização-lo de forma diferente.

Se você tem uma estrutura com std :: cordas em lá, criar um operador de fluxo e usá-lo para formatar um buffer. Você pode então memcpy que buffer para o transporte de dados. Se você tem impulso, use boost :: serialize , que faz tudo isso para você (que apontam também tem links para bibliotecas de serialização alternativos)

Notas: a maneira usual para passar um buffer variável de tamanho é começar enviando o comprimento, então, que muitos bytes de dados. Ocasionalmente você vê os dados transferidos até um delimitador é recebido (e campos dentro de que os dados estão se delimitado por um outro personagem, por exemplo, uma vírgula).

Outras dicas

Eu vejo duas partes desta pergunta: - serialização de dados através de uma rede - como passar estruturas em uma pilha de rede

Para dados serialize através de uma rede, você vai precisar de um protocolo. Não tem que ser difícil; para ASCII mesmo um cr / lf como fim pacote pode fazer. Se você usar um quadro (como MFC), pode fornecer funções de serialização para você; Nesse caso, você precisa se preocupar sobre como enviar isso em pacotes. A packetization que muitas vezes funciona bem para mim é:

<length><data_type>[data....][checksum]

Neste caso, a soma de verificação é opcional, e também zero dados é possível, por exemplo, se o sinal é transportado no data_type (isto é, Ack para acklnowedgement)

Se você está trabalhando no memcpy com as estruturas, você precisa considerar que memcpy só faz uma cópia superficial. Um ponteiro é inútil, uma vez transmitida através de uma rede; instand você deve transmitir os dados a partir desse ponteiro (ou seja, o conteúdo do seu exemplo string)

Para enviar dados dinâmicos em toda a rede que você tem as seguintes opções.

A primeira opção no mesmo pacote.

void SendData()
{
   int size;
   char payload[256];

   Send(messageType)
   Send(size);
   Send(payload)
}

Segunda opção:

void SendData()
{
   char payload[256];

   Send(messageType)
   Send(payload)
}

Embora em qualquer situação, você será confrontado com mais de uma escolha design. No primeiro exemplo, você iria enviar o tipo de mensagem, eo tamanho da carga e também, em seguida, a carga útil.

A segunda opção que você tem é que você pode enviar o tipo de mensagem e, em seguida, você pode enviar a cadeia que tem um delimitador de terminador nulo.

Apesar de uma ou outra opção não cobrir totalmente o problema a sua frente para que eu penso. Em primeiro lugar, você precisa determinar se você está construindo um jogo que tipo de protocal você estará usando, UDP? TCP? O segundo problema que você irá enfrentar é o tamanho máximo do pacote. Em seguida, em cima do que você precisa ter a estrutura no lugar para que você pode calcular o tamanho do pacote ideal que não vai ser fragmentado e perdeu para a inter web. Depois que você tem controle de banda em relação à quantidade de dados que você pode transmitir e receber entre o cliente eo servidor.

Por exemplo, a maneira que a maioria dos jogos de abordar esta situação está cada pacote é identificado com o seguinte.

MessageType
MessageSize
CRCCheckSum
MessageID
void buffer[payload]

Na situação em que você precisa para enviar dados dinâmicos que você iria enviar uma série de pacotes não apenas um. Por exemplo, se você tivesse que enviar um arquivo do outro lado da rede a melhor opção seria usar TCP / IP porque o seu streaming de protocal e garnentees que o fluxo completo chega safly para a outra extremidade. Por outro lado UDP é um pacote baseado protocal e é não fazer qualquer verificação de que todos os pacotes chegaram em ordem ou em tudo na outra extremidade.

Portanto, em conclusão.

  1. Para dados dinâmicos, enviar vários pacotes, mas com uma bandeira especial dizer mais dados é chegar para completar esta mensagem.
  2. Mantenha-o simples e se o seu trabalho com C ++ dont assumir o pacote ou dados irá conter um terminador nulo e verifique o tamanho em comparação com o carga útil se você decidir usar um terminador nulo.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top