Pergunta

Eu tenho dois programas simples configurar que compartilham dados através de um soquete do domínio Unix. Um programa lê os dados a partir de uma fila e envia-lo para o outro aplicativo. Antes de ser enviado a cada parte de dados é anexada-frente por quatro bytes com o comprimento, se ele for inferior a quatro bytes os bytes são deixados sobre o símbolo '^'.

A aplicação do cliente, em seguida, lê os primeiros quatro bytes, define um buffer para o tamanho apropriado e, em seguida, lê o resto. O problema que estou tendo é que pela primeira vez através da mensagem será enviada perfeitamente. Todas as outras vezes depois que há dados extra sendo enviado assim que uma mensagem do tipo "o que é um bom dia para fora" sairia como "o que é um bom dia para fora ?? X ??". Então, eu me sinto como um buffer não está sendo limpo corretamente, mas eu não consigo encontrá-lo.

O código do cliente:

listen(sock, 5);
for (;;) 
{
    msgsock = accept(sock, 0, 0);
    if (msgsock == -1)
        perror("accept");
    else do 
    {
        char buf[4];
        bzero(buf, sizeof(buf));
        if ((rval = read(msgsock, buf, 4)) < 0)
        perror("reading stream message");

        printf("--!%s\n", buf);

        string temp = buf;
        int pos = temp.find("^");
        if(pos != string::npos)
        {
            temp = temp.substr(0, pos);
        }

        int sizeOfString = atoi(temp.c_str());
        cout << "TEMP STRING: " << temp << endl;
        cout << "LENGTH " << sizeOfString << endl;
        char feedWord[sizeOfString];
        bzero(feedWord, sizeof(feedWord));

        if ((rval = read(msgsock, feedWord, sizeOfString)) < 0)
              perror("reading stream message");

          else if (rval == 0)
              printf("Ending connection\n");
          else
              printf("-->%s\n", feedWord);
              bzero(feedWord, sizeof(feedWord));
              sizeOfString = 0;
              temp.clear();
      } 
        while (rval > 0);
      close(msgsock);
  }
  close(sock);
  unlink(NAME);

Código Servidor

                pthread_mutex_lock(&mylock);
                string s;
                s.clear();
                s = dataQueue.front();
                dataQueue.pop();
                pthread_mutex_unlock(&mylock);

                int sizeOfString = strlen(s.c_str());
                char sizeofStringBuffer[10];

                sprintf(sizeofStringBuffer, "%i", sizeOfString);
                string actualString = sizeofStringBuffer;
                int tempSize = strlen(sizeofStringBuffer);

                int remainder = 4 - tempSize;
                int x;
                for(x =0; x < remainder; x++)
                {
                    actualString = actualString + "^";
                }

                cout << "LENGTH OF ACTUAL STRING: " << sizeOfString << endl;

                actualString = actualString + s;

                cout << "************************" << actualString << endl;
                int length = strlen(actualString.c_str());

                char finalString[length];
                bzero(finalString, sizeof(finalString));
                strcpy(finalString, actualString.c_str());

                           if (write(sock, finalString, length) < 0)
                           perror("writing on stream socket");      
Foi útil?

Solução

Ao invés de prencher o seu tamanho do pacote com '^', você estaria muito melhor apenas fazendo:

snprintf(sizeofStringBuffer, 5, "%04d", sizeOfString);

para que o valor é 0 acolchoado -. Então você não precisa analisar os caracteres '^' no código receptor

Por favor, também editar o seu código de depuração -. Só há uma write() no código atual, e isso não corresponde à sua descrição do protocolo

O ideal - dividir sua rotina de envio em uma função própria. Você também pode tirar proveito de writev() a alça coalescentes a corda segurando o campo "tamanho" com o tampão que contém os dados reais e, em seguida, enviá-los como um único write() atômica.

código não testado seguinte:

int write_message(int s, std::string msg)
{
     struct iovec iov[2];
     char hdr[5];

     char *cmsg = msg.c_str();
     int len = msg.length();

     snprintf(hdr, 5, "%04d", len);  // nb: assumes len <= 9999;

     iov[0].iov_base = hdr;
     iov[0].iov_len = 4;

     iov[1].iov_base = cmsg;
     iov[1].iov_len = len;

     return writev(s, iov, 2);
}

Outras dicas

Você tem que verificar valores de retorno de ambos write e read não só para -1 mas para curto (menos solicitado) escreve / lê. Você também parecem apenas continuar depois de imprimir um erro com perror -. Fazer uma exit(2) ou algo lá

Duas coisas:

Primeiro -. No lado do servidor que você está escrevendo para fora da extremidade do seu array

char finalString[length];
bzero(finalString, sizeof(finalString));
strcpy(finalString, actualString.c_str());

O strcpy() irá copiar personagens length+1 em finalString (personagem puxar o terminador nulo).

Em segundo lugar (e mais provável que seja o problema) - no lado do cliente que não são nulos encerra o string que você ler, portanto, o printf() irá imprimir sua seqüência, e então tudo o que está na pilha até o ponto que atinge um nulo.

Aumentar ambos os buffers por um, e você deve estar em melhor forma.

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