View Javadoc
1   /*
2    * Created on 2004-12-22
3    *
4    * klasa odpowiedzialna za komunikowanie się klienta z serwerem. Sprawdza
5    * poprawność otrzymywanych pakietów, wysyła update, łączy z serwerem.
6    */
7   package org.sourceforge.jvb3d.Network;
8   
9   import java.io.IOException;
10  import java.net.InetSocketAddress;
11  import java.util.Observable;
12  import java.util.Observer;
13  import java.util.logging.Logger;
14  
15  /***
16   * @author Łukasz Krzyżak
17   * 
18   * klasa odpowiedzialna za komunikowanie się klienta z serwerem. Sprawdza
19   * poprawność otrzymywanych pakietów, wysyła update, łączy z serwerem.
20   */
21  public class ServerData implements Observer {
22  	NetworkSender networkSender;
23  
24  	private String connectData;
25  
26  	private long seqNumber = 0;
27  	private long sendSeqNumber = 1;
28  
29  	private long lastPacketReceived = System.currentTimeMillis();
30  	
31  	private InetSocketAddress serverAddress;
32  	private Logger fLogger = Logger.getLogger("ServerData");
33  	
34  	/***
35  	 * czas, po którym stwierdzamy, że serwer jest rozłączony jesli nie dostaliśmy od niego żadnego pakietu
36  	 */
37  	public static final long serverTimeout = 1000;
38  	
39  	private NetworkClientFacade clientFacade;
40  
41  	/***
42  	 * tworzy wymagane obiekty (NetworkSender)
43  	 */
44  	public ServerData() {
45  		networkSender = new NetworkSender();
46  		clientFacade = NetworkClientFacadeHolder.getNetworkFacade();
47  	}
48  
49  	/***
50  	 * próbuje połączyc się z serwerem. Wysyła pakiet join na adres podany w
51  	 * parametrze, a następnie czeka, aż klient otrzyma pakiet connect - wtedy
52  	 * metoda update spowoduje wznowienie wykonywania i zwrócenie wartości
53  	 * otrzymanych w pakiecie.
54  	 * 
55  	 * @param server
56  	 *            adres serwera
57  	 * @return ID avatara powiązanego z tym klientem
58  	 * @throws IOException
59  	 *             jeśli coś poszło źle 
60  	 * TODO jeśli nie otrzymamy pakietu connect - wisimy na wieki
61  	 * TODO join zwraca stringa - docelowo będzie coś większego
62  	 */
63  	public synchronized String join(InetSocketAddress server)
64  			throws IOException {
65  		JoinPacket joinPacket = new JoinPacket();
66  		networkSender.send(joinPacket, server.getAddress(), server.getPort());
67  
68  		try {
69  			wait();
70  		} catch (InterruptedException e) {
71  		}
72  		
73  		serverAddress = server;
74  		return connectData;
75  	}
76  
77  	/***
78  	 * obsługuje pakiety otrzymane z sieci. Jeśli to pakiet connect - zapisuje
79  	 * zapisane w nim dane, i notyfikuje główny wątek. Jeśli to pakiet update -
80  	 * sprawdza numer SEQ, aktualizuje czas, po czym wywołuje odpowiednią metodę
81  	 * z fasady
82  	 * TODO ładniejsza obsługa wyjątków
83  	 * @param arg0 referencja do bufora
84  	 * @param arg1 
85  	 */
86  	public synchronized void update(Observable arg0, Object arg1) {
87  		try {
88  			Packet recvPacket = ((ReceivedPacketBuffer) arg0).getNextPacket();
89  			if (recvPacket instanceof ConnectPacket) {
90  				connectData = ((ConnectPacket) recvPacket).getAvatarId();
91  				notify();
92  			} else if (recvPacket instanceof UpdatePacket) {
93  				
94  				if (validatePacket((UpdatePacket) recvPacket))
95  					clientFacade.forwardUpdate((UpdatePacket)recvPacket);
96  				else
97  					fLogger.warning("Serwer otrzymał pakiet ze złym numerem seq");
98  			}
99  		} catch (Exception e) {
100 			e.printStackTrace();
101 		}
102 	}
103 
104 	private boolean validatePacket(UpdatePacket update) {
105 		
106 		if (update.getSeqNumber() <= seqNumber)
107 			return false;
108 		seqNumber = update.getSeqNumber();
109 		lastPacketReceived = System.currentTimeMillis();
110 		return true;
111 	}
112 
113 	/***
114 	 * wysyła dane przekazane w parametrze do serwera, sprawdza timeout serwera
115 	 * @param updateData dane do przesłania
116 	 * @throws TimeoutException gdy wystąpił timeout serwera
117 	 * @throws IOException gdy wystapił błąd wysyłania pakietu
118 	 */
119 	public void sendUpdate(byte[] updateData) throws TimeoutException, IOException{
120 		if(System.currentTimeMillis() - lastPacketReceived > serverTimeout) throw new TimeoutException(serverAddress);
121 		
122 		UpdatePacket updatePacket = new UpdatePacket();
123 		updatePacket.setSeqNumber(sendSeqNumber++);
124 		updatePacket.setUpdateData(updateData);
125 		networkSender.send(updatePacket, serverAddress.getAddress(), serverAddress.getPort());
126 	}
127 	
128 	/***
129 	 * brzydka funkcja do testów
130 	 * @param address
131 	 */
132 	void setServerAddress(InetSocketAddress address) {
133 		serverAddress = address;
134 	}
135 }