Qual é a melhor maneira de monitorar um soquete para novos dados e, em seguida, processar os dados?

StackOverflow https://stackoverflow.com/questions/453609

Pergunta

Por favor perdão meu C # .Net novato status. Se isso é óbvio e eu perdi-o dos docs, um link para a página relevante ou código de exemplo seria apreciada.

Eu estou trabalhando em um aplicativo que vai aceitar uma conexão de soquete TCP a partir de um aplicativo Java. (Sim, Java é necessária nessa parte. É um dispositivo Sun SPOT e Java é a única opção.) O aplicativo Java vai escrever periodicamente novos dados para o socket, e o trabalho do meu aplicativo é tomar no byte [], converso -lo a uma corda, processar os dados (atualização da interface do usuário, etc) e, possivelmente, encaminhar os dados para outro computador que executa um C semelhante # .NET aplicativo.

Aqui está o que eu fiz até agora: Agora o aplicativo gira-se uma discussão sobre o lançamento que abre um soquete. O aplicativo Java pode se conectar com êxito para a tomada de modo que está funcionando. Eu estava olhando para o método do NetworkStream beginRead eo dataAvailable, length e propriedades CanRead, mas eu não sou inteiramente certo como determinar quando eu li um pacote de dados, geralmente cerca de 512 bytes, mas pode variar.

Se o aplicativo Java grava dados para o fluxo ou há um atraso de dados (O aplicativo Java estará passando dados rapidamente.) Como posso ter certeza que eu estou lendo apenas um pacote de dados de cada vez? Se o aplicativo nulo Java termina os dados quando ele escreve, será que ajuda? Isso é suficiente?

Por fim, o soquete só irá receber uma ligação, mas eu preciso para mantê-la aberta até que haja um erro ou a conexão é encerrada. Qual é a forma mais graciosa para lidar com este aspecto? Eu não acho que fechar e reabrir com cada pacote de dados irá funcionar por causa do fogo rápido (quase em tempo real) aspecto do aplicativo Java que está sendo executado na estação base Sun SPOT. Agora, quando os termina estação de base, meu aplicativo tem uma morte alto e doloroso. :)

Obrigado pela leitura e por qualquer ajuda que você pode oferecer.

Foi útil?

Solução 3

A forma como nós resolvemos isso é ter uma combinação de caracteres sentinela e campos de largura fixa. Os dois primeiros bytes são um cabeçalho de comprimento para a totalidade do pacote. Em seguida, ler o pacote dentro de um byte [] de tampão e depois confiar na nossa própria estrutura de pacote de saber que, por exemplo, os dois primeiros bytes são cada um deles para ser interpretado como campos individuais e, em seguida, campos de cadeias são terminadas com o \ n carácter (0x0A se você está marcando em casa). Em seguida, os campos de dados longos são processados ??pela leitura em 8 bytes consecutivos, etc. Parece estar funcionando muito bem para nós, mas é, obviamente, uma solução para uma situação onde se tem controle sobre ambas as extremidades do soquete e não onde um é única capaz de controlar a uma extremidade. Espero que isso ajude alguém, também.

Outras dicas

"Se o aplicativo Java grava dados para o fluxo ou há um atraso de dados (O aplicativo Java estará passando dados rapidamente.) Como posso ter certeza que eu estou lendo apenas um pacote de dados de cada vez? "

Tenha cuidado para não assumir que você tem qualquer controle sobre os dados que acaba no qual pacote. Se você tentar enviar os dados byte { 'H', 'e', 'l', 'l', 'o' } não há nenhuma garantia de que todos esses dados serão enviados em um único pacote. Embora seja extremamente improvável, ainda é possível que cada pacote só poderia conter um único byte para que você iria receber todos os cinco bytes em 5 eventos diferentes. O ponto é, não contam com os pacotes desta maneira. Em vez disso, definir o seu próprio End Of terminadores de mensagens e simplesmente atirar todos os dados de entrada em um buffer de byte de algum tipo e ter outra função que vem em detectar se há algum destes terminadores presente. Se assim for ler até que terminator. Então diga, por exemplo, você chamar o respectivo método de envio de seu aplicativo Java contendo duas vezes os seguintes dados:

{ 'H', 'e', 'l', 'l', 'o', '\0' }
{ 'W', 'o', 'r', 'l', 'd', '\0' }

Como o aplicativo deve estar preparado para receber os dados deve ser algo como isto:

Server receives { 'H', 'e', 'l' }
Data stored in byte buffer { 'H', 'e', 'l' }
Check byte buffer for message terminator '\0'. None found. Buffer unchanged, no message processed.
Server receives { 'l', 'o', '\0', 'W' }
Data stored in byte buffer { 'H', 'e', 'l', 'l', 'o', '\0', 'W' }
Check byte buffer for message terminator '\0'. 1 found, extracted message { 'H', 'e', 'l', 'l', 'o' } and buffer updated { 'W' }

Assim, enquanto que não era exatamente uma resposta à sua pergunta original que eu acho que deveria lhe dar um empurrão na direção certa.

Uma coisa que você pode correr em é que simplesmente não há quaisquer caracteres que não poderiam ser dados em vez de terminadores de mensagens. Por exemplo, muitos arquivos contêm os dados \ 0 assim que estes iria destruir sua detecção mensagem. Como isso geralmente é tratada é através da criação de uma especificação de cabeçalho para o seu protocolo e detectar se você está esperando um cabeçalho (No caso procurando \ 0 irá denotar o fim de uma mensagem que) ou se você está esperando por uma certa quantidade de dados (que pode ser especificado pelo último cabeçalho recebido.) Se isso não faz sentido e você acha que pode precisar usar esta técnica me avise e eu vou acrescentar a esta resposta.

Quando você está lendo streaming de dados que você precisa de alguma sentinela / personagem terminação ou um tamanho conhecido dos dados para determinar quando parar de ler e processar a informação. caracteres nulos ou novas linhas são comuns. Outra técnica é usar um cabeçalho de tamanho fixo, que especifica o comprimento do corpo.

A tomada permanecerá aberta até você fechá-lo ou outros termina colaterais, nesse caso, você receberá um erro durante a leitura do soquete, que você shuold manusear. NetworkStream lança uma IOException quando o socket foi fechado do lado remoto durante uma operação de leitura ou escrita.

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