public Connection AcceptConnection() { var socket = ServerSocket.AcceptTcpClient(); var connection = new Connection(socket); Connections.Add(connection); return(connection); }
internal void Start() { ServerSocket.Start(); while (true) { ClientSocket = ServerSocket.AcceptTcpClient(); HandleAlarmClient client = new HandleAlarmClient(); client.StartClient(ClientSocket, _parent); } }
/// <summary> /// The main function Running in the thread. /// </summary> public virtual void Run() { // sockets to communicate to each of the islands var con = new TcpClient[NumIslands]; // readers and writters for communication with each island var dataIn = new BinaryReader[NumIslands]; var dataOut = new BinaryWriter[NumIslands]; // whether each client is working (and communicating with the server) or not var clientRunning = new bool[NumIslands]; // initialize the Running status of all clients for (var x = 0; x < NumIslands; x++) { clientRunning[x] = true; } try { // create a server var tempTcpListener = new TcpListener(Dns.GetHostEntry(Dns.GetHostName()).AddressList[0], ServerPort); tempTcpListener.Start(); ServerSocket = tempTcpListener; } catch (IOException) { State.Output.Fatal("Error creating a socket on port " + ServerPort); } // for each of the islands for (var x = 0; x < NumIslands; x++) { try { // set up connection with the island con[x] = ServerSocket.AcceptTcpClient(); // initialize the reader and the writer dataIn[x] = new BinaryReader(con[x].GetStream()); dataOut[x] = new BinaryWriter(con[x].GetStream()); // read the id ConnectedIslandIds[x] = dataIn[x].ReadString().Trim(); State.Output.Message("Island " + ConnectedIslandIds[x] + " logged in"); // check whether the id appears in the information at the server if (!Info.ContainsKey(ConnectedIslandIds[x])) { State.Output.Error("Incorrect ID (" + ConnectedIslandIds[x] + ")"); clientRunning[x] = false; continue; } var ieii = (IslandExchangeIslandInfo)Info[ConnectedIslandIds[x]]; // redundant check, i know.... if (ieii == null) { State.Output.Error("Can't get IslandExchangeInfo for " + ConnectedIslandIds[x]); clientRunning[x] = false; continue; } // check whether an island with this id already registered with the server if (ieii.Port >= 0) { State.Output.Error("Multiple islands are claiming the same ID (" + ConnectedIslandIds[x] + ")"); clientRunning[x] = false; continue; } // send the number of ids that will be send through the communication link dataOut[x].Write(ieii.NumIncoming); // send the capacity of the Mailbox dataOut[x].Write(ieii.MailboxCapacity); dataOut[x].Flush(); // read the address and port of the island ieii.Address = dataIn[x].ReadString().Trim(); ieii.Port = dataIn[x].ReadInt32(); State.Output.Message("" + x + ": Island " + ConnectedIslandIds[x] + " has address " + ieii.Address + " : " + ieii.Port); // re-insert the information in the hash table // info.put( id, ieii ); // unnecessary -- Sean } catch (IOException) { State.Output.Error("Could not open connection #" + x); clientRunning[x] = false; } } State.Output.ExitIfErrors(); // By this time, all Mailboxes have been started and // they should be waiting for incoming messages. this is because // in order to send the server the information about the address and port // of the Mailbox, they have to start them first. This is the reason // that makes us be able to start connecting without other synchronization // stuff right at this point. // Now, I think, we've got a 1:1 mapping of keys to items in the info hashtable // So we tell everyone who they will communicate to for (var x = 0; x < NumIslands; x++) { if (clientRunning[x]) { var ieii = (IslandExchangeIslandInfo)Info[ConnectedIslandIds[x]]; if (ieii == null) { State.Output.Warning("There is no information about island " + ConnectedIslandIds[x]); clientRunning[x] = false; continue; } try { // send the Synchronous, Modulo, Offset and size information to the current islands if (Synchronous) { dataOut[x].Write(1); } else { dataOut[x].Write(0); } dataOut[x].Write(ieii.Modulo); dataOut[x].Write(ieii.Offset); dataOut[x].Write(ieii.Size); // send the number of address-port pairs that will be sent dataOut[x].Write(ieii.NumMig); for (var y = 0; y < ieii.NumMig; y++) { var temp = (IslandExchangeIslandInfo)Info[ieii.MigratingIslandIds[y]]; if (temp == null) { State.Output.Warning("There is incorrect information on the island " + ConnectedIslandIds[x]); dataOut[x].Write(" "); dataOut[x].Write(-1); } else { State.Output.Message("Island " + ConnectedIslandIds[x] + " should connect to island " + ieii.MigratingIslandIds[y] + " at " + temp.Address + " : " + temp.Port); dataOut[x].Write(temp.Address); dataOut[x].Write(temp.Port); } } dataOut[x].Flush(); } catch (IOException) { // other errors while reading State.Output.Message("Server: Island " + IslandIds[x] + " dropped connection"); clientRunning[x] = false; continue; } catch (NullReferenceException) { // other errors while reading State.Output.Message("Server: Island " + IslandIds[x] + " dropped connection"); clientRunning[x] = false; try { dataIn[x].Close(); dataOut[x].Close(); con[x].Close(); } catch (IOException) { } continue; } } } try { // Next we wait until everyone acknowledges this foreach (BinaryReader t in dataIn) { t.ReadString(); } // Now we tell everyone to start Running foreach (BinaryWriter t in dataOut) { t.Write(RUN); t.Flush(); } } catch (IOException) { } // Okay we've sent off our information. Now we wait until a client // tells us that he's found the solution, or until all the clients // have broken connections for (var x = 0; x < con.Length; x++) { try { con[x].ReceiveTimeout = FOUND_TIMEOUT; } catch (SocketException) { State.Output.Error("Could not set the connect with island " + x + " to non-blocking."); } } var shouldExit = false; while (!shouldExit) { // check whether there is at least one client Running // otherwise the server might continue functioning just because the last client crashed or finished connection shouldExit = true; for (var x = 0; x < dataOut.Length; x++) { if (clientRunning[x]) { shouldExit = false; break; } } if (shouldExit) { break; } // sleep a while try { Thread.Sleep(new TimeSpan((Int64)10000 * SLEEP_TIME)); } catch (ThreadInterruptedException) { } for (var x = 0; x < dataOut.Length; x++) { if (clientRunning[x]) { // initialize ww string ww; // check to see if he's still up, and if he's // sent us a "I found it" signal try { ww = dataIn[x].ReadString().Trim(); } //catch (System.IO.IOException e) //{ // // means that it run out of time and got no message, // // so it should just continue with the other sockets // continue; //} catch (IOException) { // other errors while reading State.Output.Message("Server: Island " + IslandIds[x] + " dropped connection"); clientRunning[x] = false; continue; } catch (NullReferenceException) { // other errors while reading State.Output.Message("Server: Island " + IslandIds[x] + " dropped connection"); clientRunning[x] = false; try { dataIn[x].Close(); dataOut[x].Close(); con[x].Close(); } catch (IOException) { } catch (Exception) { } continue; } if (ww == null) // the connection has been broken { State.Output.Message("Server: Island " + IslandIds[x] + " dropped connection"); clientRunning[x] = false; try { dataIn[x].Close(); dataOut[x].Close(); con[x].Close(); } catch (IOException) { } } else if (ww.Equals(IslandExchange.FOUND)) // he found it! { // inform everyone that they need to shut down -- // we do not need to wrap // our PrintLn statements in anything, they just // return even if the client has broken the connection for (var y = 0; y < dataOut.Length; y++) { if (clientRunning[y]) { try { dataOut[y].Write(GOODBYE); dataOut[y].Close(); dataIn[y].Close(); con[y].Close(); } catch (IOException) { } } } // now we can just get out of all this and // quit the thread shouldExit = true; break; } else if (ww.Equals(IslandExchange.SYNC)) { WhoIsSynchronized[x] = true; var complete_synchronization = true; for (var y = 0; y < NumIslands; y++) { complete_synchronization = complete_synchronization && (!clientRunning[y] || WhoIsSynchronized[y]); } // if the number of total Running islands is smaller than the // number of islands that ask for synchronization, let them continue // Running if (complete_synchronization) { for (var y = 0; y < NumIslands; y++) { // send the okay message (the client can continue executing) if (clientRunning[y]) { try { dataOut[y].Write(IslandExchange.OKAY); dataOut[y].Flush(); } catch (IOException) { } } // reset the who_is_synchronized variable WhoIsSynchronized[y] = false; } } } } } } State.Output.Message("Server Exiting"); }
/// <summary> /// The main functionality of the Mailbox: /// waiting for incoming messages and dealing with the incoming immigrants /// </summary> public virtual void Run() { // wait for the "NumIncoming" incoming connections from different islands, and initialize // the sockets and the readers to communicate with (receive messages from) them. All the // sockets are set to be non-blocking, such that they can be checked alternatively without // waiting for messages on a particular one. for (var x = 0; x < NumIncoming; x++) { try { InSockets[x] = ServerSocket.AcceptTcpClient(); BinaryWriter dataOutput; if (CompressedCommunication) { /* * dataInput[x] = new DataInputStream(new CompressingInputStream(inSockets[x].getInputStream())); * dataOutput = new DataOutputStream(new CompressingOutputStream(inSockets[x].getOutputStream())); */ var compressedo = Output.MakeCompressingOutputStream(InSockets[x].GetStream()); var compressedi = Output.MakeCompressingInputStream(InSockets[x].GetStream()); if (compressedi == null || compressedo == null) { State.Output.Fatal("You do not appear to have JZLib installed on your system, and so may must have compression turned off for IslandExchange. " + "To get JZLib, download from the ECJ website or from http://www.jcraft.com/jzlib/"); } DataInput[x] = new BinaryReader(compressedi); dataOutput = new BinaryWriter(compressedo); } else { DataInput[x] = new BinaryReader(InSockets[x].GetStream()); dataOutput = new BinaryWriter(InSockets[x].GetStream()); } // send my id, then read an id dataOutput.Write(MyId); dataOutput.Flush(); IncomingIds[x] = DataInput[x].ReadString().Trim(); State.Output.Message("Island " + IncomingIds[x] + " connected to my Mailbox"); // set the socket to non-blocking InSockets[x].ReceiveTimeout = CHECK_TIMEOUT; Running[x] = true; } catch (IOException e) { Running[x] = false; State.Output.Fatal("An exception was generated while creating communication structures for island " + x + ". Here it is: " + e); } } State.Output.Message("All islands have connected to my client."); // variable used for deciding (based on the synchronized variable "syncVar") when to exit bool shouldExit; // enter the main loop do { // wait some (do not check all the time, cause it would be a waste of time and computational resources) try { Thread.Sleep(new TimeSpan((Int64)10000 * SLEEP_BETWEEN_CHECKING_FOR_IMMIGRANTS)); } catch (ThreadInterruptedException) { } // for each of the connections established with the islands for (var x = 0; x < NumIncoming; x++) { if (Running[x]) { try { // enter an infinite loop to receive all the messages form the "x"s island // it will exit the loop as soon as there are no more messages coming from // the "x"s island (non-blocking socket) while (true) { // read the subpop where the immigrants need to be inserted. In case there // is no incoming message, an exception will be generated and the infinite loop // will be exited (the Mailbox will search the next socket (communication link) // for incoming messages var subpop = DataInput[x].ReadInt32(); // if it gets to this point, it means that a number of individuals will be sent // it is the time to set up the receiving storages // set the socket to blocking for reading the individuals try { InSockets[x].ReceiveTimeout = 0; } catch (SocketException) { State.Output.Warning("Could not set the socket to blocking while receiving individuals in the Mailbox."); } // how many individuals will be received in the current dialogue? var how_many_to_come = DataInput[x].ReadInt32(); if (Chatty) { State.Output.Message("Receiving " + how_many_to_come + " immigrants for subpop " + subpop + " from island " + IncomingIds[x]); } // synchronize on the immigrants (such that other threads cannot access it during its // being modified) lock (Immigrants) { // in case the immigrants buffer was emptied, the person2die is not reset (it is not public) // so we have to reset it now if (NumImmigrants[subpop] == 0) { // if it was reset NextIndexPosition[subpop] = 0; // reset the person2die[x] } // loop in order to receive all the incoming individuals in the current dialogue for (var ind = 0; ind < how_many_to_come; ind++) { // read the individual try { // read the immigrant in the storage Immigrants[subpop][NextIndexPosition[subpop]] = State.Population.Subpops[subpop].Species.NewIndividual(State, DataInput[x]); //state.Output.Message( "Individual received." ); // increase the queue index if (NextIndexPosition[subpop] == Immigrants[subpop].Length - 1) { NextIndexPosition[subpop] = 0; } else { NextIndexPosition[subpop]++; } // can increment it without synchronization, as we do synchronization on the immigrants if (NumImmigrants[subpop] < Immigrants[subpop].Length) { NumImmigrants[subpop]++; } } catch (IOException) { // i hope it will also never happen :) State.Output.Message("IO exception while communicating with an island"); Running[x] = false; continue; } catch (FormatException) { // it happens when the socket is closed and cannot be doing any reading State.Output.Message("IO exception while communicating with an island"); Running[x] = false; continue; } } } // end synchronized block on "immigrants" // set the socket to non-blocking (after current set of immigrants is over) try { InSockets[x].ReceiveTimeout = CHECK_TIMEOUT; } catch (SocketException) { State.Output.Warning("Could not set the socket to non-blocking while receiving individuals in the Mailbox."); } } } //catch (InterruptedIOException e) // BRS : TODO : Find the .NET exception that we want to catch here? //{ // // here everything is ok // // just that there were no messages //} catch (IOException) { // now this is not nice // report the error so that the programmer can fix it (hopefully) State.Output.Message("IO exception while communicating with an island"); Running[x] = false; } catch (FormatException) // BRS : TODO : Verify that this is the .NET exception to expect? { // error received when some sockets break State.Output.Message("Socket closed"); Running[x] = false; } } } // again with synchronization, try to access the syncVar to check whether the Mailbox needs to finish // Running (maybe some other island already found the perfect individual, or the resources of the current // run have been wasted) lock (syncVar) { // get the value of the syncVar. If it is true, we should exit. shouldExit = syncVar[0]; } }while (!shouldExit); // close the sockets (don't care about the Running, but deal with exceptions) try { // close the ServerSocket ServerSocket.Stop(); } catch (IOException) { } for (var x = 0; x < NumIncoming; x++) { try { // close the sockets to communicate (receive messages) with the other islands InSockets[x].Close(); } catch (IOException) { continue; } } }