Server.java 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  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.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.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. control.getGui().triggerUpdateController(null);
  118. }
  119. }
  120. private HolonObjectModel createModel() {
  121. HolonObjectModel model = new HolonObjectModel();
  122. int index = 0;
  123. for(HolonElement ele :observed.getElements()) {
  124. model.add(ele, index++);
  125. }
  126. return model;
  127. }
  128. public class UpdateLoop implements Runnable{
  129. public UpdateLoop(){
  130. }
  131. @Override
  132. public void run() {
  133. sendUpdate();
  134. while(!stopped && connection) {
  135. if(checkForUpdates()){
  136. sendUpdate();
  137. }else {
  138. waitOneSecond();
  139. }
  140. }
  141. }
  142. private void waitOneSecond() {
  143. //wait one second
  144. try {
  145. TimeUnit.SECONDS.sleep(1);
  146. } catch (InterruptedException e) {
  147. }
  148. }
  149. private boolean checkForUpdates() {
  150. //TODO Delete And CheckforUpdatesReal
  151. newModelField = createModel();
  152. if(compareModels(modelField,newModelField)) {
  153. return false;
  154. }
  155. modelField = newModelField;
  156. return true;
  157. }
  158. /**
  159. * Returns true if both are the same.
  160. * @param modelField
  161. * @param newModelField
  162. * @return
  163. */
  164. private void sendUpdate() {
  165. try {
  166. if(observed == null) stopConnection();
  167. console.println("Send: [" + Command.Update + "] -> Update");
  168. out.writeByte(Command.Update);
  169. out.writeInt(modelField.size());
  170. for(HolonElementWrapper wrapper : modelField.getElements()) {
  171. out.writeUTF(wrapper.name);
  172. out.writeInt(wrapper.amount);
  173. out.writeFloat(wrapper.energy);
  174. out.writeBoolean(wrapper.enabled);
  175. }
  176. } catch (IOException e) {
  177. if(connection)console.println(e.getMessage());
  178. }
  179. }
  180. }
  181. private boolean compareModels(HolonObjectModel model, HolonObjectModel newModel) {
  182. if(model.size() != newModel.size()) {
  183. return false;
  184. }
  185. for(int i = 0; i < model.size(); i++) {
  186. if(!model.getElements().get(i).equals(newModel.getElements().get(i))) {
  187. return false;
  188. }
  189. }
  190. return true;
  191. }
  192. public void setObserved(HolonObject observed) {
  193. this.observed = observed;
  194. }
  195. public class Command {
  196. //InputCommands
  197. public static final int SetAmount = 10;
  198. public static final int SetEnable = 11;
  199. public static final int IncreaseAmount = 12;
  200. public static final int DecreaseAmount = 13;
  201. //UpdateResiveCommands
  202. public static final int Update = 20;
  203. }
  204. public class HolonObjectModel {
  205. //Field
  206. private List<HolonElementWrapper> elements;
  207. private String holonObjectName;
  208. //constructor
  209. public HolonObjectModel(){
  210. elements = new ArrayList<HolonElementWrapper>();
  211. }
  212. public void add(HolonElement ele, int index ) {
  213. String name = ele.getName();
  214. int amount =ele.getAmount();
  215. float energy = ele.getEnergyPerElement();
  216. boolean enabled = ele.isActive();
  217. elements.add(new HolonElementWrapper(name, amount, energy, enabled, index));
  218. }
  219. public int size() {
  220. return elements.size();
  221. }
  222. //Getter/Setter
  223. public List<HolonElementWrapper> getElements() {
  224. return elements;
  225. }
  226. public String getHolonObjectName() {
  227. return holonObjectName;
  228. }
  229. public void setHolonObjectName(String holonObjectName) {
  230. this.holonObjectName = holonObjectName;
  231. }
  232. }
  233. public class HolonElementWrapper{
  234. public int index;
  235. public String name;
  236. public int amount;
  237. public float energy;
  238. public boolean enabled;
  239. public HolonElementWrapper(){
  240. }
  241. public HolonElementWrapper(String name, int amount, float energy, boolean enabled, int index){
  242. this.name = name;
  243. this.amount = amount;
  244. this.energy = energy;
  245. this.enabled = enabled;
  246. }
  247. @Override
  248. public boolean equals(Object obj) {
  249. if (obj == this) {
  250. return true;
  251. }
  252. if (!(obj instanceof HolonElementWrapper)) {
  253. return false;
  254. }
  255. HolonElementWrapper element = (HolonElementWrapper) obj;
  256. return this.name.compareTo(element.name) == 0 &&
  257. this.amount == element.amount &&
  258. this.energy == element.energy &&
  259. this.enabled == element.enabled;
  260. }
  261. }
  262. }