Uso de sockets

18 respostas
P

Estou a desenvolver um pequeno jogo (faculdade) num ambiente Cliente-Servidor.

Visto que é um jogo com personagens que se movem constantemente ou seja, não é um jogo de tabuleiro, preciso de actualizar os clientes a cada momento.

Mas a minha dúvida é como o fazer?

Eu nas aulas dei o método para Serializar e Sockets. Nada mais para resolver este tipo de problema. Sendo assim, o código que recebe e manda é o seguinte:

import java.net.Socket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.File;
import java.io.FileInputStream;

public class FileClient {
	private Socket socket; 

	public FileClient() {
		try {
			this.socket = new Socket(InetAddress.getLocalHost(), 9191);
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		FileClient fc = new FileClient();
		fc.comeca();
	}

	private void comeca() {
		while(true){
			
			enviaJogo();
		}
			
		
	}

	private void enviaJogo() {
		try {
			FileOutputStream fos = new FileOutputStream("jogo.ser");
			ObjectOutputStream out = new ObjectOutputStream(fos);
			Objecto um = new Objecto("Blabla", 1);
			out.writeObject(um);
			out.close();
		} catch (IOException ex) {
			ex.printStackTrace();
		}

		File f = new File("jogo.ser");
		try {
			
			ObjectOutputStream out = new ObjectOutputStream(
					socket.getOutputStream());
			System.out.println("Transferindo o arquivo: " + f.getName());
			out.writeUTF(f.getName());
			out.writeLong(f.length());
			FileInputStream in = new FileInputStream(f);
			byte[] buf = new byte[4096];

			while (true) {
				int len = in.read(buf);
				if (len == -1)
					break;
				out.write(buf, 0, len);
			}
			out.close();
			socket.close();
			System.out.println("Pronto.");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
import java.net.ServerSocket;
import java.net.Socket;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.FileOutputStream;

public class FileServer {
	private ServerSocket ss;
	private Socket socket;

	public FileServer() {
		try {
			ss = new ServerSocket(9191);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		FileServer fs = new FileServer();
		fs.comeca();
	}

	private void comeca() {
		try {
			socket = ss.accept();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		while(true){
			
			recebeJogo();
		}
			


	}

	private void recebeJogo() {
		try {
			System.out.println("Esperando por arquivos.");
			ObjectInputStream in = new ObjectInputStream(
					socket.getInputStream());
			String fileName = in.readUTF();
			long size = in.readLong();

			System.out.println("Processando arquivo: " + fileName + " - "
					+ size + " bytes.");

			FileOutputStream fos = new FileOutputStream(fileName);
			byte[] buf = new byte[4096];
			while (true) {
				int len = in.read(buf);
				if (len == -1)
					break;

				fos.write(buf, 0, len);
			}
			fos.flush();
			fos.close();
			System.out.println("Pronto.");

		} catch (Exception ex) {
			ex.printStackTrace();
		}

		try {
			FileInputStream fis = new FileInputStream("jogo.ser");
			ObjectInputStream in = new ObjectInputStream(fis);
			Objecto novo = (Objecto) in.readObject();
			System.out.println(novo.getNome());
			in.close();
		} catch (IOException ex) {
			ex.printStackTrace();
		} catch (ClassNotFoundException ex) {
			ex.printStackTrace();
		}
	}

}

Isto é um pequeno exemplo de como mando um Objecto entre o Cliente e o Servidor. Funciona se mandar um Objecto uma vez por outra. Mas como preciso de estar constantemente a actualizar utilizei o While(true) que podia ser, por exemplo, um while(!jogoFinished); Mas nesse caso dá erro... Há outra solução possível? Usando apenas Sockets e Serialização?

18 Respostas

A

cara,

da uma olhada nesse link, uma melhor forma de se trabalhar com socket,

t+

P

Esse site pouco interessa. Isso é comunicação de sockets, isso é algo simples. O envio de mensagens, etc. Eu quero enviar Objectos e perceber como posso fazer um Cliente-Servidor.

Não mandem dicas em sites sfv :frowning: eu agradeço a ajuda, mas ao menos tentem ler a minha dúvida, não se trata de como se usa um socket… o código que fiz funciona perfeitamente. Envia, recebe o mesmo objecto.

A

cara,
é tao simples que vc ta fazendo seu codigo errado. :?

vc chegou a ver o codigo do site, te mandei para vc ter uma base.
mesmo pq se vc usar o objeto PrintWriter, vc resolve seu problema.

T+

P

No exemplo não vejo o uso de PrintWriter :frowning:

Mas a questão é o que altero no meu codigo :frowning:

P

Algo deste tipo?

BufferedReader in = new BufferedReader( new InputStreamReader( socket.getInputStream())); // O output é automaticamente enviado por PrintWriter: PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter( socket.getOutputStream())), true);

A

cara,
existe varias formas de se fazer, PrintWriter, ObjectOutputStream, mas o que falta em vc é humildade, se te passei o site é pq ele resolve seu problema, mas to achando que vc ta querendo alguem que faz seu trabalho, acho dificil vc achar isso aqui, melhor estudar.

t+

P

Não é humildade. Eu tenho código já feito. Apenas queria correcção. Mandas-me um site, q não tem dica nenhuma. Usei PrintWriter e não tem maneira de receber um Objecto. Pelo menos de maneira simples. Não faço ideia do que estás a falar. Se não quiseres dar-me orientações tudo bem. Mas não venhas falar de humildade quando as tuas dicas só baralham quem não percebe tanto do assunto.

Cumprs…

G

Qual é o erro q vc está tendo, utilizando o while(true) ?

P

java.io.EOFException at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source) at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source) at java.io.ObjectInputStream.readStreamHeader(Unknown Source) at java.io.ObjectInputStream.<init>(Unknown Source) at FileServer.recebeJogo(FileServer.java:50) at FileServer.comeca(FileServer.java:40) at FileServer.main(FileServer.java:23)

A

no site tem tudo o que vc quer, so fazer um esforço e estudar mais um pouco, a dica é o site, tudo pronto e funcionando perfeito, como te disse, ninguem aqui no site vai fazer seu trabalho da faculdade nao.

G

Tenta mover o ss.accept para dentro do while(true) e usa o método “setKeepAlive”

clientSocket = serverSocket.accept();
clientSocket.setKeepAlive(true);
P

dá este erro também

Esperando por arquivos.java.io.EOFException

	at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)
	at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)
	at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
	at java.io.ObjectInputStream.<init>(Unknown Source)
	at FileServer.recebeJogo(FileServer.java:52)
	at FileServer.comeca(FileServer.java:41)
	at FileServer.main(FileServer.java:23)
G
ping0:
dá este erro também
Esperando por arquivos.java.io.EOFException

	at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)
	at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)
	at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
	at java.io.ObjectInputStream.<init>(Unknown Source)
	at FileServer.recebeJogo(FileServer.java:52)
	at FileServer.comeca(FileServer.java:41)
	at FileServer.main(FileServer.java:23)

Dá uma olhada na linha 52 da classe FileServer. E tenta descobrir pq o seu inputstream está fechado. QQ coisa dê uma lida nesta exceção para entender melhor.

http://docs.oracle.com/javase/6/docs/api/java/io/EOFException.html

P

Estou a fazer testes. Está a dar :slight_smile:

Obrigadão ^^. Realmente não percebo qual foi o erro. Fiz ambas as coisas. Já agora, se não for muito incómodo. O metodo setKeepAlive(true) altera o que no socket? Não permite que o socket fecha a comunicação? Desculpa a ignorância.

Talvez o accept() tenha sido a causa.

De qualquer modo, agradeço a ajuda.

P

Boas de novo…

Está a dar um outro erro,

java.net.SocketException: No buffer space available (maximum connections reached?): connect at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.PlainSocketImpl.doConnect(Unknown Source) at java.net.PlainSocketImpl.connectToAddress(Unknown Source) at java.net.PlainSocketImpl.connect(Unknown Source) at java.net.SocksSocketImpl.connect(Unknown Source) at java.net.Socket.connect(Unknown Source) at java.net.Socket.connect(Unknown Source) at java.net.Socket.<init>(Unknown Source) at java.net.Socket.<init>(Unknown Source) at FileClient.comeca(FileClient.java:26) at FileClient.main(FileClient.java:20)

que faz com que o socket feche. Já estive a ler e pelo que eu percebi o S.O. tem um numero limite de ligações :(. Alguém sabe como posso resolver este erro?

P

Boas de novo…

Está a dar um outro erro,

java.net.SocketException: No buffer space available (maximum connections reached?): connect at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.PlainSocketImpl.doConnect(Unknown Source) at java.net.PlainSocketImpl.connectToAddress(Unknown Source) at java.net.PlainSocketImpl.connect(Unknown Source) at java.net.SocksSocketImpl.connect(Unknown Source) at java.net.Socket.connect(Unknown Source) at java.net.Socket.connect(Unknown Source) at java.net.Socket.<init>(Unknown Source) at java.net.Socket.<init>(Unknown Source) at FileClient.comeca(FileClient.java:26) at FileClient.main(FileClient.java:20)

que faz com que o socket feche. Já estive a ler e pelo que eu percebi o S.O. tem um numero limite de ligações :(. Alguém sabe como posso resolver este erro?

G

estou enfrentando o mesmo erro aqui

Erro de I/O:No buffer space available (maximum connections reached?): connect
verei como resolver e posto a solução

G

ping0 caso estiver usando SO linux digite: ulimit -n 65536 caso esteja usando ruindows entao vá no regedit em HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters crie uma nova entidade DWORD (MaxUserPort) com valor 65536.
apos isso basta reiniciar o ruindows que irá funcionar.

Criado 29 de novembro de 2011
Ultima resposta 4 de dez. de 2011
Respostas 18
Participantes 4