Programação Java Socket
-
19-08-2019 - |
Pergunta
Estou construindo uma aplicação simples cliente / servidor utilizando soquetes de java e experimentar com a ObjectOutputStream etc.
Eu fui seguindo o tutorial no endereço http: //java.sun .com / desenvolvedor / technicalArticles / ALT / soquetes começando a meio caminho para baixo quando se fala sobre o transporte de objetos sobre soquetes.
Veja o meu código para o cliente http: // pastebin. com / m37e4c577 No entanto, este não parece trabalho e eu não consigo descobrir o que não está funcionando. O código comentado no fundo é copiado diretamente para fora do tutorial - e isso funciona quando eu apenas usar que em vez de criar o objeto cliente.
Alguém pode ver nada eu estou fazendo errado?
Solução
O problema é a ordem que você está criando as correntes:
No servidor a partir do artigo (que eu suponho que é o que você está usando), quando uma nova conexão é aberta, o servidor abre pela primeira vez um fluxo de entrada, e, em seguida, um fluxo de saída:
public Connect(Socket clientSocket) {
client = clientSocket;
try {
ois = new ObjectInputStream(client.getInputStream());
oos = new ObjectOutputStream(client.getOutputStream());
} catch(Exception e1) {
// ...
}
this.start();
}
O código comentado exemplo utiliza a ordem inversa, primeiro, que estabelece o fluxo de saída, então o fluxo de entrada:
// open a socket connection
socket = new Socket("localhost", 2000);
// open I/O streams for objects
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
Mas o seu código faz o contrário:
server = new Socket(host, port);
in = new ObjectInputStream(server.getInputStream());
out = new ObjectOutputStream(server.getOutputStream());
O estabelecimento de um par fluxo de fluxo de saída / entrada vai parar até que eles trocaram suas informações aperto de mão, de modo que você deve coincidir com a ordem da criação. Você pode fazer isso apenas trocando as linhas 34 e 35 em seu código de exemplo.
Outras dicas
Você não está escrevendo o objeto em qualquer lugar.
Veja que apontam novamente, em algum lugar você tem que escrever:
oos.writeObject( new Date() );
Em seu código você só tem
ois.readObject();
É por isso
Apenas um lembrete.
Quando você usa keep ObjectOutputStream em mente que ele mantém um cache de referência. Se você escrever um objeto, alterar o conteúdo de objetos e, em seguida, enviar o mesmo objeto novamente, você receberá os dados duplicados. Por exemplo:
List list = new ArrayList();
list.add("value1");
out.writeObject(list);
list.clear();
list.add("value2");
out.writeObject(list);
produzirá no lado do cliente duas listas com a string "value1".
Para evitar isso, o método de reposição deve ser invocado para redefinir o cache de fluxo ao escrever a mesma referência objeto várias vezes:
List list = new ArrayList();
list.add("value1");
out.writeObject(list);
out.reset();
list.clear();
list.add("value2");
out.writeObject(list);
Provavelmente você vai gostar de aprender o primeiro mais básico.
Aqui está um exemplo que acabo codificada.
É iniciar um servidor , que atende apenas um cliente e envia um objeto e morrer.
Quando o usuário pressionar (você) entra, uma nova cliente é criado, ele se conecta ao servidor criado anteriormente e ler o objeto que servidor irá enviar.
Sem exceção é tratada aqui. Apenas para tornar as coisas mais simples, mas esta não é a maneira de exceção deve ser tratada.
Quando você entender todos os conceitos aqui, será mais fácil de entender os do tutorial.
import java.io.*;
import java.net.*;
import java.util.*;
public class SimpleServer implements Runnable {
// Creates the server, send a "date" and die.
public void run() {
try {
ServerSocket server = new ServerSocket( 8090 );
Date creationDate = new Date();
System.out.println("(Server) Server is ready "
+ "and running at " + creationDate );
Socket uniqueClient = server.accept();
// We will write using this "chained" object.
ObjectOutputStream out = new ObjectOutputStream(
uniqueClient.getOutputStream());
out.writeObject( creationDate );
// close all, at this point forget about the exceptions.
// this is lesson #1
out.close();
uniqueClient.close();
server.close();
System.out.println("(Server) The server is down");
}catch( IOException ioe ) {}
}
public static void main ( String [] args ) throws IOException ,
ClassNotFoundException {
Thread serverThread = new Thread( new SimpleServer() );
serverThread.start(); // start the server thread ... doh..
System.out.println("(Client) Press enter when you want "+
" to connect to the server...");
Scanner scanner = new Scanner( System.in );
scanner.nextLine();
Socket client = new Socket("localhost", 8090 );
// Read from this object.
ObjectInputStream in = new ObjectInputStream( client.getInputStream() );
Date date = ( Date ) in.readObject();
System.out.println("(Client) Current time is: " + new Date() );
System.out.println("(Client) Object read from server : " + date );
in.close();
client.close();
}
}
Espero que isso ajude.
Se você tentou um depurador que teria lhe disse onde estava o problema. (Talvez não porque)
O problema que tenho é que ObjectOutputStream escreve um cabeçalho e ObjectInputStream lê esse cabeçalho. Você criou o ObjectInputStream primeiro que significa que ele está tentando ler um cabeçalho que nunca será escrita.
Solução:. Sempre criar o ObjectOutputStream primeiro e flush () antes de criar o ObjectInputStream
É melhor abrir uma outputStream
porque um fluxo de saída não bloqueia. Então, você tem o fluxo de entrada que aguarda uma Stream
. Depois de todos os fluxos, você gravar o fluxo e lave-lo - outputStream.flush()
para enviar os bytes de dados. Você também vai precisar de um método na outra extremidade para ler a entrada, se é simplesmente inputStream.read()
que lê cada byte como um inteiro para uma char
, ou usando um BufferedReader
ou Scanner
. Eu usei quase todos os métodos possíveis, mas o método mais eficaz para o envio é outputStream.write(String)
que escreve uma seqüência de char
s como byte
s na corrente e inputStream.read()
leitura lê um único char
. Espero que isso ajude.