Comunicação Client/Server TCP/IP Socket

Caros colegas,

Sou iniciante em comunicação Socket TCP/IP.

Estou desenvolvendo um programa em Java que se comunica com um Robo Japonês através de Socket TCP/IP, onde este Robo implementa a parte Client e meu programa deve implementar o lado Server para estabelecer comunicação e para que meu programa envie mensagens de texto que representam ordens de tarefas ao Robo Client.

Estou conseguindo estabelecer a comunicação e enviar algumas mensagens de ordem, as quais são executadas pelo cliente Robo, normalmente.

Contudo, em algum momento esta comunicação se perde e eu não estou conseguindo determinar quando isso ocorre.

Este é o trecho do codigo que estou usando:

    public void waitForConnection() {
        if (this.serverSocket!=null) {
            try {
                setSocket(serverSocket.accept());
                if (getSocket()!=null) {
                    Date date = new Date(System.currentTimeMillis());
                    System.out.println("Client Connected on "+this.getSocket()+" "+date);
                    bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    bufferedWriter = new PrintStream(socket.getOutputStream());   
                    this.setConnected(true);
                }
            } catch (IOException ex) {
                Logger.getLogger(IPv4ServicePort.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public void setPort(int port) {
        if (service.getSocketType()==service.IPv4_SOCKET_SERVER) {
            try {
                setServerSocket(new ServerSocket(port));
                
            } catch (IOException ex) {
                Logger.getLogger(IPv4ServicePort.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        this.port = port;
    }

De fato, utilizo estes dois métodos para estabelecer a porta que o Server irá ouvir, e responder a requisições do Client com mensagens de ordem. O Cliente pergunta se existe alguma ordem a ser executada e o servidor responde com a ordem que precisa ser executada.

Todavia o cliente consegue a conexão que é aceita no pelo serverSocket.accept() que gera um Socket ; Depois disso, a troca de mensagens ocorre e em algum momento o Robo “reclama” que não conseguiu mais conectar no servidor naquela porta. Só que no servidor eu não consigo perceber o porque esta falha ocorreu, nem sei como reestabelecer tal comunicação. Tentei usar novamente o método serverSocket.accept(); mas não sei exatamente em que momento devo utilizálo novamente. Teria eu que fechar o Socket antigo e depois abrir um novo serverSocket.accept() para gerar um novo Socket ? Mas em que momento faria isso ?

Estou cheio de dúvidas pois a documentação não trata desta comunicação, apenas diz que tenho que implementar um Server Socket TCP/IP e responder as mensagens. Então a documentação trata muito especificamente das mensagens em sí, fala sobre o número da porta a ser usara, mas não fala mais nada sobre a implementação do servidor TCP/IP.

Peço ajuda dos colegas;

[]s.

ola! q robo eh esse?

A primeiríssima coisa que você, obrigatoriamente, tem que fazer é se debruçar no manual desse robô e entender exatamente como está organizado o protocolo de comunicação.
Muito provavelmente será um protocolo binário, e o PrintStream não irá te ajudar nesse caso.

O robô deve estar enviando algum tipo de mensagem de KEEP_ALIVE para o server, para garantir que ainda está conectado. Quando o robô não recebe resposta, ele fecha a conexão.
Você não vê nenhum erro pois isso não é um problema. É muito comum que aplicações TCP/IP se comuniquem dessa forma.

Não adianta jogar qualquer dado para o robô, nem ficar só parado na linha. Você deve primeiro aprender a fala a língua dele (e esperamos que não seja japonês).

Dica: Baixe também o wireshark, pois ele permite ver a comunicação entre sua aplicação e o robô.

Eu imagino que ele realmente utiliza o envio de algum KEEP_ALIVE, algum byte que represente que a comunicação está “viva”, isso em baixo nível, mas esse byte não chega no método read() (que é o input de Stream do BufferedReader). De fato, acredito até que o ServerSocket deve estar respondendo a esse KEEP_ALIVE em baixo nível automaticamente por um tempo, mas que depois para. Se não for o ServerSocket quem responde isso, não sei quem é mas o fato é que a comunicação permanece funcionando por um tempo indeterminado, mas não consegui perceber em que momento ela “para”. Parece que em determinado momento onde o Robo deseja enviar uma próxima mensagem, memsmo depois de já ter enviado mensagens anteriores, ele não consegue mais enviar… Não sei determinar qual seria o caracter que ele envia e deseja ter de retorno para reconhecer que a comunicação está viva. Ou mesmo do lado server, qual seria o caracter que o Server deve observar se continua recebendo para saber se a comunicação está “viva” ou “morreu” para descartar o Socket morto e se prontificar a estabelecer uma nova. Acho que esse controle é feito a um nível que não estou percebendo acesso de controle, em camada de transporte, rede ou enlace. Como controlar essas camadas ao ponto de determinar que a comunicação parou para deixar o sistema “pronto” para ouvir uma nova conexão? Ou como não permitir que essa comunicação já existente seja finalizada inesperadamente?

De fato a comunicação a nível de aplicação é feita por caracteres ASCII trocados pelo Client e pelo Server. Uso o PrintStream para envio dos caracteres, porque foi o exemplo que achei na Net, mas não sei exatamente se deveria utilizar outra classe ou qual classe caberia melhor para comunicações com caracteres ASCII. Se alguém puder sugerir outra classe, agradeço.

Grato,

Adriano.

Você já estudou o protocolo do robô? Já leu o manual? O que dizia?
Baixou o wireshark? Viu se no momento do travamento rolou alguma mensagem na rede?
Do que eu indiquei para você fazer, o que você fez e o que aconteceu?

O ServerSocket não faz nenhum keep_alive automático. Se isso existir, será uma mensagem específica do robô, e o Java não teria como prevê-la.
Como já falei, de nada adianta usar o PrintStream se o protocolo do robô for binário.
O PrintStream espera implicitamente por um \n, o que pode não vir nesse tipo de comunicação.
Você deve certificar-se com 100% de certeza que o protocolo do robô envia esse caractere em absolutamente todas as mensagens.

Para entender melhor como operar com um protocolo binário, leia:

Além disso, também repito a pergunta do Maurício: Que raios de robô é esse?
É bem mais fácil te ajudar se também soubermos com que equipamento você está lidando.

Vini,

Se quizer conhecer o Robo, o link está aqui:

https://www.beckmancoulter.com/wsrportal/wsrportal.portal?_nfpb=true&_windowLabel=UCM_RENDERER&_urlType=render&wlpUCM_RENDERER_path=%2Fwsr%2Fdiagnostics%2Fclinical-products%2Fchemistry%2Fau680%2Findex.htm

O protocolo, manual, etc. eu já estudei de ponta-a-ponta. Este não é o primeiro projeto desse tipo que faço. Já fiz vários outros, só que por comunicação serial RS232, mas este é o primeiro que faço por LAN/IP.

Com relação ao /n, vc fala do ASCII 13 (retorno de carro), eu sei q nesse protocolo ele não usa isso para controle. No entando para receber os bytes tenho usado o método read() do buffererReader e não o PrintStream. E tem chegado bytes normalmente independente do /n.

Independente disso, estou convencido que alguém no lado Server envia ou ecoa algum sinal para o Robo avisando que está ligado, pois quando eu fecho a aplicação, ou seja, o programa que eu mesmo fiz, o robô reclama dizendo que a conexão foi fechada. Como ele saberia disso se o Java não enviasse alguma “coisa” implicitamente para avisar ele? Se não for o Java, é o Windows ou o hardware da Ethernet, ou o driver, sei lá, mas alguém tá fazendo isso em algum nível, com certeza. Está havendo algum tipo de “ECHO” automático ou coisa do tipo, que faz com que o Cliente saiba quando o Server fecha a conexão…

Eu baixei o tal wireshark e vou testar hoje. Depois posto o resultado.

[]s.

Ah, legal, bom saber que você sabe bem do que está falando. :slight_smile:
A maior parte do pessoal que posta sobre sockets no GUJ nunca operou um protocolo binário, por isso a minha insistência.

Enfim, acho que a melhor forma de lidar com o problema, se você já conhece bem a comunicação, é mesmo baixar o wireshark e ver o que está trafegando pela rede. Assim você vê se o robô enviou algum pacote que passou batido na hora da leitura, ou alguma situação que na documentação não ficou lá muito clara. Também seria possível ver se a conexão está sendo fechada inesperadamente e exatamente por que lado.