Server.java 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. package Connection.socket;
  2. import java.net.*;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import java.util.concurrent.TimeUnit;
  6. import classes.HolonElement;
  7. import classes.HolonObject;
  8. import ui.controller.Control;
  9. import java.io.*;
  10. public class Server implements Runnable{
  11. private ServerSocket serverSocket;
  12. private Socket clientSocket;
  13. private DataOutputStream out;
  14. private DataInputStream in;
  15. private boolean stopped = false;
  16. private boolean connection = false;
  17. private ui.view.component.Console console;
  18. private HolonObject observed;
  19. private HolonObjectModel modelField;
  20. private HolonObjectModel newModelField;
  21. private Control control;
  22. public Server(int port, ui.view.component.Console console, HolonObject observed, Control control) throws IOException {
  23. this.observed = observed;
  24. this.console = console;
  25. this.control = control;
  26. //Bind Port
  27. serverSocket = new ServerSocket(port);
  28. //Wait for Connection
  29. Thread serverThread = new Thread(this);
  30. serverThread.start();
  31. this.modelField = createModel();
  32. this.newModelField = createModel();
  33. }
  34. public void stopServer() throws IOException {
  35. stopped = true;
  36. stopConnection();
  37. if(serverSocket != null)serverSocket.close();
  38. console.println("Server Closed");
  39. }
  40. private void stopConnection() throws IOException {
  41. connection = false;
  42. if(in != null)in.close();
  43. if(out != null)out.close();
  44. if(clientSocket != null)clientSocket.close();
  45. }
  46. @Override
  47. public void run() {
  48. while(!stopped) {
  49. try {
  50. //Wait for new Connection
  51. console.println("Wait for Connection..");
  52. clientSocket = serverSocket.accept();
  53. console.println("Connection from " + clientSocket.getInetAddress() + ":" + clientSocket.getPort());
  54. connection = true;
  55. out = new DataOutputStream(clientSocket.getOutputStream());
  56. in = new DataInputStream(new BufferedInputStream(clientSocket.getInputStream()));
  57. if(observed == null) stopConnection();
  58. this.modelField = createModel();
  59. Thread updateThread = new Thread(new UpdateLoop());
  60. updateThread.start();
  61. //InputLoop
  62. try {
  63. inputLoop();
  64. }catch(EOFException e){
  65. console.println("Connection Closed");
  66. }
  67. stopConnection();
  68. }
  69. catch(SocketException e){
  70. //ServerSocket is closed
  71. stopped = true;
  72. }
  73. catch (IOException e) {
  74. e.printStackTrace();
  75. }
  76. connection = false;
  77. }
  78. }
  79. private void inputLoop() throws IOException {
  80. while (connection) {
  81. //WaitForInput
  82. byte inputByte = in.readByte();
  83. //UpdateHoleg
  84. if (inputByte == Command.SetAmount) {
  85. if(observed == null) stopConnection();
  86. console.println("Res: [" + inputByte + "] -> SetAmount");
  87. int index = in.readInt();
  88. //int amount = in.readInt();
  89. //modelField.getElements().get(index).amount = amount;
  90. //observed.getElements().get(index).setAmount(amount);
  91. }else if (inputByte == Command.SetEnable) {
  92. if(observed == null) stopConnection();
  93. console.println("Res: [" + inputByte + "] -> SetEnable");
  94. int index = in.readInt();
  95. boolean enabled = in.readBoolean();
  96. modelField.getElements().get(index).enabled = enabled;
  97. observed.getElements().get(index).setActive(enabled);
  98. }else if (inputByte == Command.IncreaseAmount) {
  99. if(observed == null) stopConnection();
  100. console.println("Res: [" + inputByte + "] -> IncreaseAmount");
  101. int index = in.readInt();
  102. //modelField.getElements().get(index).amount++;
  103. HolonElement ele = observed.getElements().get(index);
  104. //ele.setAmount(ele.getAmount()+1);
  105. }else if (inputByte == Command.DecreaseAmount) {
  106. if(observed == null) stopConnection();
  107. console.println("Res: [" + inputByte + "] -> DecreaseAmount");
  108. int index = in.readInt();
  109. //modelField.getElements().get(index).amount--;
  110. HolonElement ele = observed.getElements().get(index);
  111. //ele.setAmount(ele.getAmount()-1);
  112. } else{
  113. console.println("Res: [" + inputByte + "] -> unknown");
  114. }
  115. control.calculateStateAndVisualForCurrentTimeStep();
  116. control.updateCanvas();
  117. }
  118. }
  119. private HolonObjectModel createModel() {
  120. HolonObjectModel model = new HolonObjectModel();
  121. int index = 0;
  122. for(HolonElement ele :observed.getElements()) {
  123. model.add(ele, index++);
  124. }
  125. return model;
  126. }
  127. public class UpdateLoop implements Runnable{
  128. public UpdateLoop(){
  129. }
  130. @Override
  131. public void run() {
  132. sendUpdate();
  133. while(!stopped && connection) {
  134. if(checkForUpdates()){
  135. sendUpdate();
  136. }else {
  137. waitOneSecond();
  138. }
  139. }
  140. }
  141. private void waitOneSecond() {
  142. //wait one second
  143. try {
  144. TimeUnit.SECONDS.sleep(1);
  145. } catch (InterruptedException e) {
  146. }
  147. }
  148. private boolean checkForUpdates() {
  149. newModelField = createModel();
  150. if(compareModels(modelField,newModelField)) {
  151. return false;
  152. }
  153. modelField = newModelField;
  154. return true;
  155. }
  156. /**
  157. * Returns true if both are the same.
  158. * @param modelField
  159. * @param newModelField
  160. * @return
  161. */
  162. private void sendUpdate() {
  163. try {
  164. if(observed == null) stopConnection();
  165. console.println("Send: [" + Command.Update + "] -> Update");
  166. out.writeByte(Command.Update);
  167. out.writeInt(modelField.size());
  168. for(HolonElementWrapper wrapper : modelField.getElements()) {
  169. out.writeUTF(wrapper.name);
  170. //out.writeInt(wrapper.amount);
  171. out.writeFloat(wrapper.energy);
  172. out.writeBoolean(wrapper.enabled);
  173. }
  174. } catch (IOException e) {
  175. if(connection)console.println(e.getMessage());
  176. }
  177. }
  178. }
  179. private boolean compareModels(HolonObjectModel model, HolonObjectModel newModel) {
  180. if(model.size() != newModel.size()) {
  181. return false;
  182. }
  183. for(int i = 0; i < model.size(); i++) {
  184. if(!model.getElements().get(i).equals(newModel.getElements().get(i))) {
  185. return false;
  186. }
  187. }
  188. return true;
  189. }
  190. public void setObserved(HolonObject observed) {
  191. this.observed = observed;
  192. }
  193. public class Command {
  194. //InputCommands
  195. public static final int SetAmount = 10;
  196. public static final int SetEnable = 11;
  197. public static final int IncreaseAmount = 12;
  198. public static final int DecreaseAmount = 13;
  199. //UpdateResiveCommands
  200. public static final int Update = 20;
  201. }
  202. public class HolonObjectModel {
  203. //Field
  204. private List<HolonElementWrapper> elements;
  205. private String holonObjectName;
  206. //constructor
  207. public HolonObjectModel(){
  208. elements = new ArrayList<HolonElementWrapper>();
  209. }
  210. public void add(HolonElement ele, int index ) {
  211. String name = ele.getName();
  212. //int amount =ele.getAmount();
  213. float energy = ele.getEnergy();
  214. boolean enabled = ele.isActive();
  215. elements.add(new HolonElementWrapper(name, energy, enabled, index));
  216. }
  217. public int size() {
  218. return elements.size();
  219. }
  220. //Getter/Setter
  221. public List<HolonElementWrapper> getElements() {
  222. return elements;
  223. }
  224. public String getHolonObjectName() {
  225. return holonObjectName;
  226. }
  227. public void setHolonObjectName(String holonObjectName) {
  228. this.holonObjectName = holonObjectName;
  229. }
  230. }
  231. public class HolonElementWrapper{
  232. public int index;
  233. public String name;
  234. public float energy;
  235. public boolean enabled;
  236. public HolonElementWrapper(){
  237. }
  238. public HolonElementWrapper(String name, float energy, boolean enabled, int index){
  239. this.name = name;
  240. this.energy = energy;
  241. this.enabled = enabled;
  242. }
  243. @Override
  244. public boolean equals(Object obj) {
  245. if (obj == this) {
  246. return true;
  247. }
  248. if (!(obj instanceof HolonElementWrapper)) {
  249. return false;
  250. }
  251. HolonElementWrapper element = (HolonElementWrapper) obj;
  252. return this.name.compareTo(element.name) == 0 &&
  253. this.energy == element.energy &&
  254. this.enabled == element.enabled;
  255. }
  256. }
  257. }