Pergunta

Eu estou projetando um servidor de jogo e eu nunca fiz nada como isso antes. Eu só estava me perguntando o que uma boa estrutura para um pacote de dados seria sábio? Eu estou usando TCP se isso importa. Aqui está um exemplo, e o que eu estava pensando em usar a partir de agora:

(cada valor entre parêntesis é um byte)

[Packet length][Action ID][Number of Parameters]
[Parameter 1 data length as int][Parameter 1 data type][Parameter 1 data (multi byte)]
[Parameter 2 data length as int][Parameter 2 data type][Parameter 2 data (multi byte)]
[Parameter n data length as int][Parameter n data type][Parameter n data (multi byte)]

Como eu disse, eu realmente nunca fiz nada como isso antes, então o que eu tenho acima poderia ser touro completo, que é por isso que eu estou pedindo;). Além disso, está passando o comprimento total do pacote mesmo necessário?

Foi útil?

Solução

Passando o comprimento total do pacote é uma boa idéia. Pode custar mais dois bytes, mas você pode espreitar e esperar que o soquete para ter um pacote completo pronto para saborear antes de receber. Isso torna o código mais fácil.

No geral, eu concordo com brazzy, um mecanismo de serialização idioma fornecido é preferível sobre qualquer self-made.

Além de que (eu acho que você está usando uma linguagem C-ish sem serialização), gostaria de colocar o ID pacote como os primeiros dados sobre a estrutura de pacote de dados. IMHO isso é algum tipo de convenção, porque o primeiro membro de dados de um struct é sempre na posição 0 e qualquer struct pode ser abatido para que, dados de identificação de outra forma anónimos.

Seu compilador pode ou não produzir estruturas embalados, mas de que maneira você pode alocar um buffer, leia o pacote e, em seguida, quer lançar a estrutura de acordo com o primeiro membro de dados. Se você está fora de sorte e não produz estruturas embalados, certifique-se de ter um método de serialização para cada estrutura que irá construir a partir da memória (obviamente não-destino).

extremidade é um fator, especialmente em linguagens C-like. Certifique-se de deixar claro que os pacotes são do mesmo endianness sempre ou que você pode identificar um endian diferente com base em uma assinatura ou algo assim. Uma coisa estranha que é muito legal: C # e .NET parece ter sempre dados em convenção little-endian quando você acessá-los usando como discutido neste post aqui. Descobriu que quando portar uma aplicação tal para Mono em um dom Legal, mas se você tiver que a instalação você deve usar os meios de serialização de C # de qualquer maneira.

Além disso, sua aparência configuração muito bem!

Outras dicas

Comece por considerar uma muito mais simples invólucro básica: Tag, Length, Value (TLV). Seu pacote básico vai olhar, então assim:

[Tag] [Length] [Value]

tag é um identificador de pacotes (como o seu ID ação).

Comprimento é o comprimento do pacote. Você pode precisar isso para dizer se você tem o pacote completo. Ele também irá permitir que você descobrir quanto tempo a parte de valor é.

Valor contém os dados reais. O formato deste pode ser qualquer coisa.

No seu caso acima, os dados do valor contém uma nova série de estruturas TLV (tipo de parâmetro, comprimento, valor). Você realmente não precisa enviar o número de parâmetros, como você pode trabalhar a partir do comprimento de dados e andando de dados.

Como já foi dito, gostaria de colocar o ID pacote (Tag) em primeiro lugar. A menos que você tem preocupações de plataforma cruzada, eu consideraria envolvendo objeto serializado do seu aplicativo em um TLV e enviá-lo através do fio assim. Se você cometer um erro ou quiser mudar mais tarde, você sempre pode criar uma nova tag com uma estrutura diferente.

Veja Wikipedia para mais detalhes sobre TLV .

Para evitar reinventar a roda, qualquer protocolo de serialização irá trabalhar para nos dados fio (por exemplo, XML, JSON), e que você pode considerar a olhar para BEEP para a estrutura básica do protocolo.

BEEP é resumido bem em seu documento de FAQ como ' uma espécie de álbum 'melhores hits' dos truques usados ??por protocolo designers aplicação experientes desde o início dos anos 80. '

Não há nenhuma razão para fazer algo tão complicado assim. Eu vejo que você tem um ID ação, então eu suponho que haveria um número fixo de ações.

Para cada ação, você definiria uma estrutura de dados, e então você iria colocar cada um desses valores na estrutura. Para enviá-lo ao longo do fio, basta alocar soma (sizeof (struct.i)) bytes para cada elemento em sua estrutura. Portanto, o seu pacote ficaria assim:

[action ID][item 1 (sizeof(item 1 bytes)][item 1 (sizeof(item 2 bytes)]...[item n (sizeof(item n bytes)]

A idéia é, você já sabe o tamanho e tipo de cada variável em cada lado da conexão é, assim você não precisa enviar essa informação.

Para strings, você pode simplesmente jogar 'em em em forma de terminação nula, e então quando você 'saber' para procurar uma string com base no seu tipo de pacote, iniciar a leitura e à procura de um nulo.

-

Outra opção seria usar '\ r \ n' para delinear as suas variáveis. Isso exigiria alguma sobrecarga, e você teria que usar texto, em vez de valores binários para números. Mas de que maneira você poderia usar apenas readline para ler cada variável. Seus pacotes ficaria assim

[action ID]
[item 1 (as text)]
...
[item n (as text)]

-

Finalmente, simplesmente serialização de objetos e passá-los para baixo o fio é uma boa maneira de fazer isso também, com a menor quantidade de código para escrever. Lembre-se que você não deseja otimizar prematuramente, e que inclui o tráfego de rede também. Se ele sair você precisa espremer um pouco mais desempenho, mais tarde, você pode voltar e descobrir um mecanismo mais eficiente.

E confira o Google buffers de protocolo , que supostamente são uma maneira extreemly rápido para serialize dados em uma maneira de plataforma neutra, como uma espécie de XML binário, mas sem elementos aninhados. Há também JSON é, o que é outra codificação neutra plataforma. Usando buffers de protocolo ou JSON significaria que você não teria que se preocupar sobre como codificar especificamente as mensagens.

Você quer que o servidor para suportar vários clientes escritos em linguagens diferentes? Se não, provavelmente não é necessário especificar a estrutura exatamente; em vez usar qualquer facilidade para serialização de dados suas ofertas de linguagem, simplesmente para reduzir o potencial de erros.

Se você precisa a estrutura a ser portáteis, os olhares acima OK, mas você deve especificar coisas como endianness e codificação de texto bem nesse caso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top