» Início » Programação » Java » Conexão via Sockets
 
Avaliação: | Publicado em: 28/02/2007
Conexão via Sockets
Dayvid Lima Desenvolvedor Java há mais de 5 anos, atualmente consultor java em empresa multinacional utilizando recursos avançados da tecnologia J2EE com servidores de aplicação em plataforma Solaris para gerenciamento de redes e integração de sistemas.


Hoje iremos criar uma aplicação dividida em duas partes, uma será um "server" que ficará "ouvindo" uma porta pré-definida por nós e a outra parte será um "client" que fará o acesso via sockets nesse servidor para trocar informações.

Esse conceito é muito utilizado para realizar acesso a equipamentos e/ou outros computadores para troca de informações, tanto utilizando aplicações que utilizam um "server" próprio quanto aplicações que necessitam acessar um outro tipo de servidor como por exemplo um servidor de Telnet.

Iremos primeiro criar nosso "server", para esse desenvolvimento estou utilizando o Eclipse (link para ele no final da matéria), porém podemos criar e rodar essa aplicação sem a utilização de qualquer IDE, apenas tendo o JDK na máquina.

Abaixo seguem os códigos das aplicações.

Server.java

import java.io.*;
import java.net.*;

public class Server {

    // porta que esse servidor ficara "ouvindo"
    private final int PORT = 5050;
   
    public static void main(String[] args){
        Server server = new Server();
        server.start();
    }

    public void start(){
       
        ServerSocket ss = null;
        Socket s = null;
       
        OutputStream out = null;
        DataOutputStream dataOut = null;

        String message = null;

        try {
            ss = new ServerSocket(this.PORT);
            System.out.println("Server on-line na porta: " + this.PORT);
           
            while(true){
                // espera aqui por algum acesso
                s = ss.accept();
               
                System.out.println("usuario conectado");
               
                // cria um canal de comunicao com esse socket
                out = s.getOutputStream();
                dataOut = new DataOutputStream(out);
               
                // envia msgs para o cliente quando ele iniciar uma conexao
                dataOut.writeUTF("==== Ola seja bem-vindo ao Server ====\r\n");
                dataOut.writeUTF("- digite algo e tecle ENTER\r\n");
                dataOut.writeUTF("- para sair digite FIM e tecle ENTER\r\n");
                dataOut.writeUTF("- para parar o server digite SHUTDOWN e tecle ENTER\r\n\r\n");
                   
                BufferedReader innet = new BufferedReader(new InputStreamReader(s.getInputStream()));
               
                // recebe as mensagens enviadas pelo client
                while((message = innet.readLine()) != null){

                    System.out.println("msg recebida: " + message);

                    // tratamentos especiais
                    // desconecta o client
                    if(message.equalsIgnoreCase("fim") || message.equalsIgnoreCase("shutdown")){
                        dataOut.writeUTF("bye bye!");
                        System.out.println("usuario desconectado");
                        innet.close();
                        break;
                    }
                }
                if(message.equalsIgnoreCase("shutdown")){
                    break;
                }
            }
        }
        catch(IOException e){
            System.out.println("Erro na inicializacao do server: " + e.getMessage());
        }
        finally {
            try {
                if(s != null) s.close();
                if(ss != null) ss.close();
            }
            catch(IOException e){
                System.out.println("Erro ao tentar fechar as conexoes: " + e.getMessage());
            }
        }
        System.out.println("Servidor finalizado!");
    }
}


Client.java

import java.io.*;
import java.net.*;

public class Client {

    private final String SERVER_IP = "127.0.0.1"; // IP do server
    private final int SERVER_PORT = 5050; // porta que o server esta "ouvindo"
   
    Socket echoSocket = null;
   
    public static void main(String[] args){
        Client client = new Client();
        client.start();
    }

    public void start(){
        PrintWriter out = null;
        BufferedReader in = null;
        BufferedReader stdIn = null;
        String entrada = "";
        String mensagem = " ";

        try {
            echoSocket = new Socket(this.SERVER_IP, this.SERVER_PORT);
            out = new PrintWriter(echoSocket.getOutputStream(), true);
           
            in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));

            // recebe as primeiras linhas enviadas pelo server
            while((mensagem != null) && (!mensagem.equals(""))){
                mensagem = in.readLine();
                System.out.println(mensagem);
            }           

            stdIn = new BufferedReader(new InputStreamReader(System.in));
           
            // envia para o server tudo que o usuário digitar no client
            do {
                entrada = stdIn.readLine();
                out.println(entrada);
            } while ((entrada != null) && !entrada.equalsIgnoreCase("fim") && !entrada.equalsIgnoreCase("shutdown"));
           
            // recebe a mensagem de bye bye do server
            mensagem = in.readLine();
            System.out.println(mensagem);
           
        } catch (UnknownHostException e) {
            System.err.println("Nao conseguiu achar o server " + this.SERVER_IP + ": " +  e.getMessage());
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Nao conseguiu abrir a conexao com o server " + this.SERVER_IP + ": " + e.getMessage());
            System.exit(1);
        } finally {
            try {
                if(stdIn != null) stdIn.close();
                if(in != null) in.close();
                if(out != null) out.close();
                if(echoSocket != null) echoSocket.close();
            } catch (IOException e) {
                System.err.println("erro ao tentar fechar as conexoes: " + e.getMessage());
                System.exit(1);
            }
        }
    }   
}

Entendendo o funcionamento:

O Server:

O que o server faz é ficar "ouvindo" uma determinada porta (no nosso caso a porta 5050), receber tudo que for informado nessa porta e mostrar na tela.
Para isso temos alguns passos básicos:
    1 - importar os pacotes necessários para se trabalhar com sockets
    2 - definir a porta que queremos "ouvir"
    3 - criar a conexão (começar a "ouvir")
    4 - mostrar na tela tudo que conseguir capturar pela porta que estamos "ouvindo"

Os pacotes necessários para utilização de sockets são:
    import java.io.*;
    import java.net.*;

Com eles temos os componentes necessários para criação de um servidor socket, para o tráfego de dados desse servidor e para os tratamentos de erros (exceptions).

Aqui definimos qual porta queremos que o nosso server fique "ouvindo".
    private final int PORT = 5050;

Agora criamos a conexão em sim, é aqui que ele começa a "ouvir" essa porta:
    ss = new ServerSocket(this.PORT);

Dizemos ao server para aguardar por alguma conexão:
    s = ss.accept();

Assim que ele receber uma conexão na porta que ele está "ouvindo" ele cria um canal de comunicação com quem acessou essa porta:
    out = s.getOutputStream();
    dataOut = new DataOutputStream(out);

E começa a receber as mensagens enviadas:
    BufferedReader innet = new BufferedReader(new InputStreamReader(s.getInputStream()));
               
    while((message = innet.readLine()) != null){
        System.out.println("msg recebida: " + message);
    ...


Caso a mensagem enviada seja "FIM" ele desconecta o client, e caso a mensagem seja "SHUTDOWN" ele desconecta o client e para o server.

    if(message.equalsIgnoreCase("fim") || message.equalsIgnoreCase("shutdown")){
    dataOut.writeUTF("bye bye!");
        System.out.println("usuario desconectado");
        innet.close();
        break;
    }


Caso a mensagem enviada seja "shutdown" devemos sair também do while(true) por isso temos esse outro if:
    if(message.equalsIgnoreCase("shutdown")){
        break;
    }


O Client:

O Client acessa uma PORTA em um IP pré-definido, recebe as mensagens de boas-vindas do servidor, e envia para o server tudo que for digitado.

Para isso também temos alguns passos básicos:
    1 - importar os pacotes necessários para se trabalhar com sockets
    2 - definir o ip e a porta que queremos acessar
    3 - criar a conexão com esse IP e essa PORTA
    4 - receber as mensagens de boas-vindas
    5 - enviar para o server tudo que for digitado

Os pacotes necessários para utilização de sockets são:
    import java.io.*;
    import java.net.*;

Com eles temos os componentes necessários para fazer a conexão via sockets com algum servidor, trocar mensagens com o mesmo e para os tratamentos de erros (exceptions).

Aqui temos duas contantes onde definimos o IP de onde vai estar o server e a porta que mandamos o server ficar "ouvindo", caso o server esteja na sua própria máquina você pode deixar o IP como "127.0.0.1".

    private final String SERVER_IP = "127.0.0.1"; // IP do server
    private final int SERVER_PORT = 5050; // porta que o server esta "ouvindo"

Agora criamos a conexão com o server:
            echoSocket = new Socket(this.SERVER_IP, this.SERVER_PORT);
            out = new PrintWriter(echoSocket.getOutputStream(), true);

E recebemos todas as mensagens que o server nos enviar no momento da conexão:
    in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));

    // recebe as primeiras linhas enviadas pelo server
    while((mensagem != null) && (!mensagem.equals(""))){
        mensagem = in.readLine();
        System.out.println(mensagem);
    }


Agora fazemos com que o client fique lendo tudo que for digitado pelo usuário e vá enviando para o server:
    // envia para o server tudo que o usuário digitar no client
    do {
        entrada = stdIn.readLine();
        out.println(entrada);
    } while ((entrada != null) && !entrada.equalsIgnoreCase("fim") && !entrada.equalsIgnoreCase("shutdown"));

Fazendo funcionar:

Existem diversas formas de compilar e rodar o programa mostrado aqui, segue abaixo os passos para rodar a partir da linha de comando do DOS:

    1 - salve o primeiro código em um arquivo chamado Server.java
    2 - salve o segundo código em um arquivo chamado Client.java
    3 - no prompt do DOS e/ou shell do Linux/Unix, vá até o diretório onde salvou os arquivos
    4 - para compilar digite: javac Server.java Client.java
Para rodar a aplicação você irá precisar de duas janelas do DOS , uma para o Server e outra para o Client.

    1 - Abra duas janelas (dois prompts) do DOS e entre no diretório onde você compilou os arquivos
    2 - Na primeira janela você deve executar o Server com o comando: java Server
    3 - Na segunda janela você deve executar o Client com o comando: java Client

Agora tudo que for digitado no Client será recebido pelo Server e mostrado na janela do server.

Você pode rodar o Server em uma máquina e o Client em outra, basta para isso colocar no Client o endereço IP da máquina onde o Server está rodando. Também é possível utilizar outra porta para a comunicação;

Veja aqui alguns "screen shots" do Server e do Client rodando em minha máquina:


Server rodando



Client acessando o Server

Espero que tenham gostado do artigo, abraços e até o próximo.
Dayvid

Links relacionados

Thiago Sciotta <thiagog3@gmail.com>
Parabens! Primeira coluna de sockets em português com tanto detalhamento como o seu! Continue assim :D
Muito bom! Parabéns! Agora ficou fácil entender Sockets em java!

Gostaria muito que, agora voce escrevesse algo desse assunto com um server recebendo multiplas conexões.

Obrigado.
Excelente artigo. Bem claro e objetivo. Deu pra entender perfeitamente.
Valeu!!

Dayvid Lima
Obrigado a todos pelo apoio e comentários.
Abraços,
Dayvid
Nilson Deitz <nilsondeitz@yahoo.com.br>
Parabéns Dayvid. Deveria exitir mais pessoas como você pois compartilha seus conhecimentos com os outros.
Muito bom o código exemplo e as explicações, parabéns.
Marcelo S. Oliveira <scisses@gmail.com>
caramba meus conhecimentos aumentaram bastantes depois de dessa leitura que eu fiz.
Seu codigo e bem elegante cara valew
Joao Alfredo <nhsjuaum@gmail.com>
Ótimo artigo.. Muito bem explicado, fui obrigado a deixa meu recado! Continue assim..
Piruli
Por fin encuentro a alguien que explica detenidamente la programación de un socket, la compilación y ejecución.

Muchas gracias
Tiago Soczek <tiago@osczke.net>
Parabéns! Ficou muito bom! Só falta agora implementá-lo c/ Thread's!
aureo farias <aureosc@hotmail.com>
quero entrar no atrativa e ñ to conseguindo por causa de eerro de conexão socket como posso atuar??