Array
(
)

Comunicação Socket Duas Vias com somente uma porta

Pablo Oliveira
   - 12 jan 2011

Boa tarde, amigos.
Estou com um problema para resolver um bocado complicado.
Estou implementando a integração com um aparelho via Socket TCP/IP. O protocolo deste aparelho funciona de uma maneira em que assim que o aparelho for conectado, ele manda uma string de autorização para o computador servidor, que deve estar escutando o mesmo. Ao validar esta string, é necessário retornar um ACK para o aparelho dizendo que a autenticação do mesmo foi aceita, e a partir daí toda a comunicação com o aparelho é feita na via reversa, ou seja, o computador servidor mandando comandos para o aparelho, e este aparelho respondendo ACK ou NACK conforme for o caso.
Normalmente, isso é feito utilizando duas portas, mas o aparelho só permite uma configuração de porta de comunicação, e aí após retornar o ACK para a autenticação do aparelho, duas coisas acontecem:
1. Se desconectar o socket e abrir um socket novo, cliente do aparelho, o aparelho recusa a conexão exigindo novamente uma autenticação;2. Se não desconectar o socket e tentar utilizar a mesma conexão para enviar dados, não há resposta alguma do aparelho, com a conexão sendo forçadamente cancelada.
O código que estou utilizando é o seguinte (nomes das classes alteradas para não revelar o aparelho).
#Código

        public ServidorAparelho(int Porta, String IDAparelho)        {            // do Manual de Integradores do DigiREP            /*Quando DigiREP se conecta ao servidor, ele enviará uma mensagem de com o número da               sua MRP, deve-se calcular o CRC e se estiver correto envia-se um ACK, caso contrário derruba-              se a conexão com este DigiREP.               Sugerimos que após a autenticação seja enviado o cadastro da empresa, pois o DigiREP               não irá cadastrar nenhuma pessoa se não possuir o cadastro da empresa e em seguida envia-              se o tipo de validação biométrica, pois o tipo de validação padrão é Cartão ou Biometria.              */            this.port = Porta;            this.deviceID = IDAparelho;
            TcpListener listener = new TcpListener(IPAddress.Any, this.port);            listener.Start();            using (TcpClient client = listener.AcceptTcpClient())            {                NetworkStream stream = client.GetStream();                byte[] message = new byte[1024];                int bytesRead;                String receivedTextBuffer = "";
                bytesRead = stream.Read(message, 0, 1024);
                if (bytesRead > 0)                {                    receivedTextBuffer = ByteUtils.getStringFromBytes(message);                }
                if (!(String.IsNullOrEmpty(receivedTextBuffer)))                {                    receivedTextBuffer = receivedTextBuffer.Replace("[tagcod]        public ServidorAparelho(int Porta, String IDAparelho)        {            // do Manual de Integradores do DigiREP            /*Quando DigiREP se conecta ao servidor, ele enviará uma mensagem de com o número da               sua MRP, deve-se calcular o CRC e se estiver correto envia-se um ACK, caso contrário derruba-              se a conexão com este DigiREP.               Sugerimos que após a autenticação seja enviado o cadastro da empresa, pois o DigiREP               não irá cadastrar nenhuma pessoa se não possuir o cadastro da empresa e em seguida envia-              se o tipo de validação biométrica, pois o tipo de validação padrão é Cartão ou Biometria.              */            this.port = Porta;            this.deviceID = IDAparelho;
            TcpListener listener = new TcpListener(IPAddress.Any, this.port);            listener.Start();            using (TcpClient client = listener.AcceptTcpClient())            {                NetworkStream stream = client.GetStream();                byte[] message = new byte[1024];                int bytesRead;                String receivedTextBuffer = "";
                bytesRead = stream.Read(message, 0, 1024);
                if (bytesRead > 0)                {                    receivedTextBuffer = ByteUtils.getStringFromBytes(message);                }
                if (!(String.IsNullOrEmpty(receivedTextBuffer)))                {                    receivedTextBuffer = receivedTextBuffer.Replace("\0", "");                    if (this.ValidateAuthString(receivedTextBuffer))                    {                        ReturnAckTo(stream);                        //listener.Stop();
                        //stream.Close();                        //client.Close();
                        //TcpClient sender = new TcpClient();                        //sender.Connect("10.0.6.100", 9000);
                        //stream = sender.GetStream();
                        Mensagem deviceMsg = new Mensagem();
                        deviceMsg = "teste";
                        byte[] msgToSend = deviceMsg.buildMessage();
                        stream.Write(msgToSend, 0, msgToSend.Length);                        if (stream.CanRead)                        {                            // receber a resposta para saber se a mensagem foi aceita pelo aparelho.                            bytesRead = stream.Read(message, 0, 1024);
                            if (bytesRead > 0)                            {                                receivedTextBuffer = ByteUtils.getStringFromBytes(message);                            }                        }                    }                    else                    {                        ReturnNackTo(stream);                        listener.Stop();                    }                }                else                {                    ReturnNackTo(stream);                    listener.Stop();                }
                stream.Close();            }        }[/tagcod]", "");                    if (this.ValidateAuthString(receivedTextBuffer))                    {                        ReturnAckTo(stream);                        //listener.Stop();                         //stream.Close();                        //client.Close();                         //TcpClient sender = new TcpClient();                        //sender.Connect("10.0.6.100", 9000);                         //stream = sender.GetStream();                         Mensagem deviceMsg = new Mensagem();                         deviceMsg = "teste";                         byte[] msgToSend = deviceMsg.buildMessage();                         stream.Write(msgToSend, 0, msgToSend.Length);                        if (stream.CanRead)                        {                            // receber a resposta para saber se a mensagem foi aceita pelo aparelho.                            bytesRead = stream.Read(message, 0, 1024);                             if (bytesRead > 0)                            {                                receivedTextBuffer = ByteUtils.getStringFromBytes(message);                            }                        }                    }                    else                    {                        ReturnNackTo(stream);                        listener.Stop();                    }                }                else                {                    ReturnNackTo(stream);                    listener.Stop();                }                 stream.Close();            }        }

Pablo Oliveira
   - 19 jan 2011

Já resolvido, obrigado.