1
2
3
4
5
6
7
8 package org.sourceforge.jvb3d.Network;
9
10 import java.net.DatagramSocket;
11 import java.net.DatagramPacket;
12 import java.net.InetSocketAddress;
13 import java.net.SocketException;
14 import java.net.SocketTimeoutException;
15 import java.io.ByteArrayInputStream;
16 import java.io.IOException;
17 import java.io.ObjectInputStream;
18 import java.util.logging.*;
19
20 /***
21 * @author Łukasz Krzyżak
22 *
23 * Klasa odpowiada za odbieranie pakietów z sieci, przekazywanie ich do bufora
24 * odbiorczego i uruchomienie notyfikacji obiektów które obserwują bufor.
25 */
26 public class NetworkReceiver extends Thread {
27 /***
28 * socket służący do komunikacji instancji programu z innymi kopiami
29 */
30 public static DatagramSocket listeningSocket = null;
31
32 private DatagramPacket recvPacket;
33
34 private ReceivedPacketBuffer packetBuffer = null;
35
36 private boolean terminate = false;
37
38 private ObjectInputStream objectInputStream = null;
39
40 private ByteArrayInputStream byteArrayInputStream = null;
41
42 private static final int maxPacketSize = 4096;
43
44 private static final int socketTimeout = 1000;
45
46 private static final Logger fLogger = Logger.getLogger("NetworkReceiver");
47
48 /***
49 * Wiąże obiekt z podanym portem
50 *
51 * @param port
52 * numer portu na którym ma słuchać socket
53 * @throws SocketException jeśli wystąpi błąd socketu
54 * @throws IOException jeśli wystąpi błąd przesyłania
55 */
56 public NetworkReceiver(int port) throws SocketException, IOException {
57 if(port == 0)
58 listeningSocket = new DatagramSocket();
59 else
60 listeningSocket = new DatagramSocket(port);
61 listeningSocket.setSoTimeout(socketTimeout);
62
63 byte[] dataBuffer = new byte[maxPacketSize];
64
65 byteArrayInputStream = new ByteArrayInputStream(dataBuffer);
66 recvPacket = new DatagramPacket(dataBuffer, maxPacketSize);
67 }
68
69 /***
70 * ustawia timeout socketu
71 * @param timeout czas w ms
72 * @throws SocketException jeśli podano błędną wartość
73 */
74 public void setTimeout(int timeout) throws SocketException {
75 listeningSocket.setSoTimeout(timeout);
76 }
77
78 /***
79 * powoduje zakończenie nasłuchiwania na danym sockecie i zakończenie wątku
80 *
81 */
82 public void finish() {
83 terminate = true;
84 }
85
86 /***
87 * zamyka socket i odpina go od portu
88 *
89 */
90 public void terminate() {
91 listeningSocket.close();
92 }
93
94 /***
95 * Wiąże obiekt z buforem
96 *
97 * @param buffer
98 * obiekt bufora z którym należy powiązać receivera
99 */
100 public void connectToBuffer(ReceivedPacketBuffer buffer) {
101 packetBuffer = buffer;
102 }
103
104 /***
105 * Uruchamia nasłuchiwanie na sockecie. Jeśli zostanie odebrany pakiet -
106 * zostaje przekazany do bufora, a następnie bufor jest informowany o
107 * konieczności notyfikacji observerów.
108 *
109 * @throws NullPointerException
110 * wyjątek rzucany, jeśli próbujemy wystartować metodę, a nie
111 * powiązaliśmy obiektu z buforem
112 *
113 */
114 public void run() {
115 if (packetBuffer == null)
116 throw new NullPointerException();
117 while (!terminate) {
118 try {
119 listeningSocket.receive(recvPacket);
120
121 byteArrayInputStream.reset();
122 if (objectInputStream == null)
123 objectInputStream = new ObjectInputStream(
124 byteArrayInputStream);
125 else
126 byteArrayInputStream.skip(4);
127
128 Packet receivedPacket = (Packet) objectInputStream.readObject();
129 receivedPacket.setSourceAddress((InetSocketAddress)recvPacket.getSocketAddress());
130 packetBuffer.addPacket(receivedPacket);
131 packetBuffer.notifyObservers();
132 } catch (SocketTimeoutException e) {
133 if(!terminate) fLogger.fine(e.toString());
134 } catch (IOException e) {
135 throw new NullPointerException(e.toString());
136 } catch (ClassNotFoundException e) {
137 throw new NullPointerException(e.toString());
138 }
139 }
140 }
141 }