3

I've made a simple UDP chat server and client

Client sends a packet containing a string, server receives it.

Upon receipt, the server should be able to tell if the IP AND Port number are in a list of Clients.

I made an object class called ClientDetails,

class ClientDetails {
   int port; 
   String name;
   InetAddress address;

    ClientDetails(InetAddress address, int port, String name) {
        this.address = address;
        this.port = port;
        this.name = name;
    }

and in the Server I create an ArrayList of that object to hold the details of active clients.

I have constructed some If statements and corresponding methods to perform most of the operations, but the crux is finding out whether the user is in the list or not on every packet received.

I want to use something like

if (!IsCurrentlyAUser){
then addNewUserToList();
else checkUserNameValid//ensures the String sent is not one of the keywords(who, whoami, etc)
 addNewUser();}

The idea is that IsCurrentlyAUser checks a method CheckClientExists,

private boolean checkClientExists(InetAddress ip, int port, String name){


    if (!clientList.contains(ip) && !clientList.contains(port)){
    return false;
}
     return true;

    }

Clearly this won't work, but I don't know how to make it or come up with something more viable.

EDIT: To clarify the problem and possibly complicate things:

The check is based on a clients IP AND Port. In that instance, only the ip and port are checked among the records. If they exist, the client continues, if they don't, they get added, wherein the name entered will be checked.

EDIT:

Updated ClientDetails with the following

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((address == null) ? 0 : address.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + port;
return result;
}





@Override
public boolean equals(Object obj) {
if (this == obj)
    return true;
if (obj == null)
    return false;
if (getClass() != obj.getClass())
    return false;
ClientDetails other = (ClientDetails) obj;
if (address == null) {
    if (other.address != null)
        return false;
} else if (!address.equals(other.address))
    return false;
if (name == null) {
    if (other.name != null)
        return false;
} else if (!name.equals(other.name))
    return false;
if (port != other.port)
    return false;
return true;

}

Running the following in the Main Server

    if(request.equals("who") ||request.equals("whoami")||
        request.equals("all")||request.equals("bye")){
         //do something 
          System.out.println("User Entered Invalid Name ");
         }else{
              System.out.println("User Entered a Valid Name ");
               clientName =request;
              clients.add(new ClientDetails(clientIP,clientPort,clientName));
                    }
             System.out.println("set contains " +clients.toString());

seems to not prevent duplicates, which suggests that the hash/equals is wrong. This was generated by eclipse, which is the best I could do.


IMPORTANT: See Will Ness' comment below.

Your question implies that the order doesn't matter. (But since the lists may be infinite, the order may be more important than you think!) Anyway, if the order doesn't matter, and you have encountered list comprehensions, that's one approach you could use. Here's an example.

λ> let xs = "abcdef"
λ> let ys = "ABCDEFGHI"
λ> [(x,y) | x <- xs, y <- ys]
[('a','A'),('a','B'),('a','C'),('a','D'),('a','E'),('a','F'),('a','G'),('a','H'),('a','I'),('b','A'),('b','B'),('b','C'),('b','D'),('b','E'),('b','F'),('b','G'),('b','H'),('b','I'),('c','A'),('c','B'),('c','C'),('c','D'),('c','E'),('c','F'),('c','G'),('c','H'),('c','I'),('d','A'),('d','B'),('d','C'),('d','D'),('d','E'),('d','F'),('d','G'),('d','H'),('d','I'),('e','A'),('e','B'),('e','C'),('e','D'),('e','E'),('e','F'),('e','G'),('e','H'),('e','I'),('f','A'),('f','B'),('f','C'),('f','D'),('f','E'),('f','F'),('f','G'),('f','H'),('f','I')]

Note that all of the tuples involving 'a' are printed first, then those involving 'b', and so on. Why does that matter? Well suppose the list is infinite. A query like this will return instantly:

(1,'a') `elem` [(x,y) | x <- [1..], y <- ['a'..]]

But one like this will take a LOOOOONG time:

(200000,'a') `elem` [(x,y) | x <- [1..], y <- ['a'..]]

If order matters, or you haven't encountered list comprehensions, or don't want to use them, luqui's approach is probably what you're looking for.

4

1 に答える 1

0

メソッドhashCode と equalsClientDetailsを実装することで、クラスを改善できます。

次に、それらのデータを単一のSetに格納できるようになります。

class Clients {

 private final Set<ClientDetails> clients = new HashSet<>();

 public boolean checkClientExists(InetAddress ip, int port, String name){

   return  clients.contains(new ClientDetails(ip,port,name));   

 }

//More code for client management.
}

クラスは単純な構造ホルダーであるため、そのオブジェクトを作成して、そのような要素が既に作成されていることを確認するだけです。ただし、これらすべて (ip、port、name) をできるだけ早く構造体にラップし、アプリケーションで使用するようにしてください。

于 2013-04-04T10:58:42.790 に答える