[Tut] Using a List to only allow one connection (fixes SYI... i think)

Results 1 to 5 of 5
  1. #1
    Member meiscooldude is offline
    MemberRank
    Nov 2006 Join Date
    79Posts

    [Tut] Using a List to only allow one connection (fixes SYI... i think)

    Allowing Only One Connection for every IP Address.


    Intro: Ok, Well I noticed that allot of people are complaining about this so called 'SYI', So I spent about 5 minutes and made it so you can only have one connection for every IP Address... I have not tested this with SYI, but I am pretty sure it will work. I am also going to attempt to teach you something, so read carefully.


    What you will learn: How to create, and use the 'LIST' data structure. And some new Vocabulary.


    So, as I said above we are going to be using the 'List' data structure. Essentially, a List is an Array of Object, but is itself an Object. List has a few very useful object methods that we can use to our advantage. I have them listed below.



    Important Methods of the List Object:

    VOID: clear(); //removes everything from the list

    BOOLEAN: add(Object o); //adds the specific object to the list (returns true if the object was added)

    BOOLEAN: contains(Object o); //returns true if the specific object is in the list

    BOOLEAN: remove(Object o); //removes the specific object from the list (returns true if the object was removed)


    How we instantiate* a List:

    Because the class List is actually an Interface**, we cannot simply do this:
    Code:
    List list = new List();
    We have to create a list like so:
    Code:
    List list = new ArrayList();


    Using a list:

    Alright, lets create a small class just for learning purposes, and have a List added to it.

    Code:
    import java.util.List;
    import java.util.ArrayList;
    
    class Test
    {
       public static void main(String args[])
       {
          List list = new ArrayList();
       }
    }
    Now this 'Test' class we just created is nice, it creates instantiates a new List object, and it is ready to use, but it doesn't do anything yet. So, lets use some of our methods we have posted above to make this List useful. I am also going to use an array, that way you can compare for yourself the differences.

    List:

    Code:
    import java.util.List;
    import java.util.ArrayList;
    
    class Test
    {
       public static void main(String args[])
       {
          List list = new ArrayList();
          list.add("Hello World!");
          list.add("Hello World Again!");
       }
    }
    Array:

    Code:
    import java.util.List;
    import java.util.ArrayList;
    
    class ArrayTest
    {
       public static void main(String args[])
       {
          String[] array = new String[2];
          array[0] = "Hello World!";
          array[1] = "Hello World Again!";
       }
    }

    Do you see that with an array, we have to know what the next index would be? And Also, if you look closely, there is a limit to how many Strings you can put in your array. With a list, you don't have to know the next Index, you just call ".add(object)", and you are not limited to the initial size of the data structure.

    Now, lets say we want to see if our list and our array contain the String "Hello World!", we would do that like so:

    List:

    Code:
    import java.util.List;
    import java.util.ArrayList;
    
    class Test
    {
       public static void main(String args[])
       {
          List list = new ArrayList();
          list.add("Hello World!");
          list.add("Hello World Again!");
          
          if(list.contains("Hello World!"))
          {
             System.out.println("Your List contains it!");
          }
          else
          {
             System.out.println("Your List Does not contains it!");
          }
       }
    }
    Array:

    Code:
    import java.util.List;
    import java.util.ArrayList;
    
    class ArrayTest
    {
       public static void main(String args[])
       {
          String[] array = new String[2];
          array[0] = "Hello World!";
          array[1] = "Hello World Again!";
          
          for(int i = 0; i < 2; i++)
          {
             if(array[i].equals("Hello World!"))
             {
                System.out.println("Your Array contains it!");
                break;
             }
             else
             {
                System.out.println("Your Array Does not contains it!");
             }
          }
       }
    }
    As you can see, the '.contains(object)' method in List makes it allot easier to check if an Object is contained, instead of messing with for loops. And using a List helps prevent IndexOutOfBound Exception.
    [size=8pt]Note: When calling '.contains(object)' on a list, it loops through for you, so your not gaining any speed.[/size]

    Alright, well I believe you can hopefully figure out the '.remove(object)'and the '.clear()' methods yourself , so I won't waist any more lines.


    Using a List to only allow one Connection per IP
    (Don't just skip to this!!!)


    Step 1: So, Lets open up Server.java, or w/e your equivalent is. And add the imports for List, and ArrayList.

    Code:
    import java.util.List;
    import java.util.ArrayList;
    Now that we have imported the List and the ArrayList class, we can go ahead and initialize our List somewhere.

    Step 2: Now that we can use the List class, Lets create our List Object, Im going to call mine... connections.

    Code:
    public static List connections = new List();
    Put this somewhere in Server.java... It is public and static so we can access it from a Client Object.

    Step 3: Alright, so we've added a new list object, we can now use it from anywhere in our program. Now lets put it to some use. In the Run() void, you will see a while loop, before we change anything in the while loop, lets have a look at it.

    This is about what I have:
    Code:
    while(true) 
    {
       java.net.Socket s = clientListener.accept();
       s.setTcpNoDelay(true);
       String connectingHost = s.getInetAddress().getHostName();
       if (true)
       {
          misc.println("ClientHandler: Accepted from " + connectingHost + ":" + s.getPort());
          playerHandler.newPlayerClient(s, connectingHost);
       }
       else
       {
          misc.println("ClientHandler: Rejected " + connectingHost + ":" + s.getPort());
          s.close();
       }
    }
    If you don't understand what is going on inside the loop, Its creating a new Socket, then waiting for someone to connect to it, Once someone does, It gets their 'Host Name'. Then it goes through the 'If-Else' statements, so... if(true), basically its asking if true is true, then do this,... So its always going to print out "ClientHandler: Accepted from blah blah blah...." , and then fork off a new thread for a player. Then start the loop again.

    Step 4: Now, that we know there is some refactoring*** to do in this loop lets get started on integrating it with your List.

    Well, Everytime someone connects we will want to add their Host Name to our connections list. So, right after,
    Code:
    misc.println("ClientHandler: Accepted from " + connectingHost + ":" + s.getPort());
    Add

    Code:
    connections.add(connectingHost);
    So, now, anytime someone connects it adds their Host Name to a list of other Host Names. Just doing that does'nt help us... So lets use our '.contains(Object)' method...

    In our 'If' statement, replace

    Code:
    if(true)
    with

    Code:
    if(!connections.contains(connectingHost))
    So, now, if my connections list doesn't already have that Host Name in it, then it will accept the connection... Right there only allowing one Connection for every IP Address...

    Step 5: If you have some programming skill, you may have already noticed that I forgot to tell you to remove a clients Host Name from the list if they get disconnected... Because If I don't, they will not be able to connect again.

    So, Lets fix this, Open up Client.java and go to your destruct() void.

    In there, you will see

    Code:
    misc.println("ClientHandler: Client "+playerName+" disconnected.");
    disconnected = true;
    Right after that, add

    Code:
    server.connections.remove(mySock.getInetAddress().getHostName());
    Now, that will remove the players Host Name from your connections list, allowing the to connect again.


    That's it, I hope you enjoyed this Tutorial, and see the possibilities of how you can use the 'List' Data Structure. Try loading your banned IP/PlayerNames into a list, or something else. HAVE FUN!



    Vocab:
    *Instantiation: Creates a new instance of an Object (when all the memory is allocated for it)
    **Interface: An interface is similar to an Abstract Class, but basically is a contract that a class that inherits it will contain all its methods.
    ***Refactor: Re-writing your code


    Credits: Me


  2. #2
    change my name already! I Rule MU is offline
    MemberRank
    Apr 2007 Join Date
    JerseyLocation
    4,220Posts

    Re: [Tut] Using a List to only allow one connection (fixes SYI... i think)

    wow this is awsome. When i put in my new webclient ill put this in too. Thanks!

  3. #3
    Member meiscooldude is offline
    MemberRank
    Nov 2006 Join Date
    79Posts

    Re: [Tut] Using a List to only allow one connection (fixes SYI... i think)

    Quote Originally Posted by I Rule MU View Post
    wow this is awsome. When i put in my new webclient ill put this in too. Thanks!
    Ya, lists are an amazing data structure, In my internship they are teaching me about all the different types of Data Structures, I learned lists a while ago, but haven't thought of a way to apply them to RS Private servers till today...

  4. #4
    change my name already! I Rule MU is offline
    MemberRank
    Apr 2007 Join Date
    JerseyLocation
    4,220Posts

    Re: [Tut] Using a List to only allow one connection (fixes SYI... i think)

    Quote Originally Posted by meiscooldude View Post
    Ya, lists are an amazing data structure, In my internship they are teaching me about all the different types of Data Structures, I learned lists a while ago, but haven't thought of a way to apply them to RS Private servers till today...
    And im glad you did. Now we wont have those annoyances we get with those extra connections.

  5. #5
    right + down + X GhostSnyper is offline
    MemberRank
    May 2006 Join Date
    AZ, USALocation
    2,818Posts

    Re: [Tut] Using a List to only allow one connection (fixes SYI... i think)

    Forgot about lists :P I had an array that handled it, but was very inefficient. Overall, this is a really good, and you've made one hell of a comeback :) *thumbs up*



Advertisement