2013-12-24 6 views
2

동일한 서버/IP에 대한 다중 클라이언트 연결을 효율적으로 처리하는 방법은 무엇입니까?Java 다중 클라이언트 소켓 처리

현재 새 플레이어가 게임에 참여할 때마다 새 스레드를 만드는 서버 소켓이 있습니다.

플레이어를 어떻게 처리합니까? IP 주소를 통해이 작업을 수행 할 수 있다고 생각하지만 그 작업을 수행하는 방법을 알지 못합니다. 또한 로컬 연결을 테스트하고 플레이어가 동일한 IP에서 여러 계정을 사용할 수있는 방법으로는이 방법이 효율적으로 보이지 않습니다.

나는 게임에서 그들을 부팅하고 자신의 계정을 수정할 수있는 능력을 가진 플레이어를 관리하고 싶습니다. 미리 감사드립니다. :)

+0

정의 '선수들을 관리하고,'선수들을 관리하고, ... – EJP

+0

"동일한 서버/IP에 대한 여러 클라이언트 연결을 처리합니다". 서버에서 소켓 연결을 닫을 수 있어야합니다. 내가 원하는 어느 연결에 대해서도. – user3130731

+0

귀하의 질문에 대한 답변은 이것이 어떤 종류의 게임인지에 따라 크게 달라집니다. 각 클라이언트의 입력을 가져 와서 처리하고 매틱마다 보내야합니까? udp 또는 tcp 소켓을 사용하고 있습니까? 의사 소통이 안정 될 것인가 아니면 파열 될 것인가? – Gibby

답변

3

이 내 네트워킹 (당신이 원하는 경우 의견을 주시기 바랍니다) 할 방법은 다음과 같습니다

"마스터"서버가 ServerSocket의이 포함되어 있습니다. "Sub"Server는 개별 클라이언트를 처리합니다. 비유로 레스토랑을 생각해보십시오. "마스터 서버"는 접수입니다. 클라이언트가 들어 오면 클라이언트의 요청을 받아 그를 "서브 서버"에 지정합니다. "서브 서버"는 웨이터입니다. 그들은 개별 클라이언트 요청을 처리합니다. 따라서 다음과 같은 결과를 얻을 수 있습니다.

public class Server extends Thread { 

    final private ServerSocket m_serverSocket; 
    final public static int MAX_CLIENTS = 3000; 
    final private SubServer[] m_clientConnections = new SubServer[ MAX_CLIENTS ]; 

    public Server(int port) throws IOException { 
     this.m_serverSocket = new ServerSocket(port); 
     start(); 
    } 

    @Override 
    public void run() { 
     while (!this.interrupted()) { 
      //wait for clients 
      Socket connection = this.m_serverSocket.accept(); 
      assignConnectionToSubServer(connection); 
     } 
    } 

    public void assignConnectionToSubServer(Socket connection) { 
     for (int i = 0 ; i < MAX_CLIENTS ; i++) { 

      //find an unassigned subserver (waiter) 
      if (this.m_clientConnections[ i ] == null) { 
        this.m_clientConnections[ i ] = new SubServer(connection , i); 
        break; 
      } 
     } 
    } 

    protected class SubServer extends Thread { 

     final private int m_id; 
     final private Socket m_connection; 

     //you can store additional client properties here if you want, for example: 
     private int m_gameRating = 1500; 

     public SubServer(Socket connection , int id) { 
      this.m_id = id; 
      this.m_connection = connection; 
      start(); 
     } 

     @Override 
     public void run() { 
      while(!this.interrupted()) { 
       //process a client request 
       //this is for you to implement 
      } 
     } 

     //as an example, if you read String messages from your client, 
     //just call this method from the run() method to process the client request 
     public void process(String message) { 

     } 

     /** 
     * terminates the connection with this client (i.e. stops serving him) 
     */ 
     public void close() { 
      try { 
       this.m_connection.close(); 
      } catch (IOException e) { 
       //ignore 
      } 
     } 
    } 
} 

따라서 모든 클라이언트에 서비스를 제공 할 수 있어야합니다.

clientConnection[ i ].close(); 

각 클라이언트의 ID는 SubServer 개체에 저장됩니다.

원할 경우 각 서브 서버 내에 추가 등록 정보를 저장할 수 있습니다. 일단 네트워킹이 설정되면 네트워크에 연결되지 않은 프로그램처럼 "정상적인"것입니다.

편집 :

바로 지금 당신 질문에 대답하려면 :

Q. 어떻게 내가 선수를 처리하나요?

A. 플레이어는 SubServer 개체를 사용하여 플레이어를 처리합니다. SubServer 클래스 내에서 추가 기능을 정의하여 원하는 기능을 구현할 수 있습니다. 특히 사용자를 구별해야하는 경우 게임을 시작하기 전에 고유 한 사용자 이름을 제공하도록합니다. 내가 좋아하는 것

Q.이 close() 메소드를 사용하여

A. 부팅 게임에서 그들을 부팅하고 자신의 계정 수정할 수있는 능력의 선수를 관리 할 수 ​​있도록하고 서버 연결이 끊어집니다 . SubServer 오브젝트에서 계정 특성을 지정하고 서버가 실행되는 동안이 특성을 수정할 수 있습니다.

편집 : 그래서 지금

, 당신은 모든 사용자

와의 JList을 관찰하는 ActionListener가있을 수 있습니다
public class UserListListener implements ActionListener { 

    final private Server m_networking; 

    //you need to pass a reference to the server to your listener 
    //you may also need to pass a reference to the user interface (JList) to your listener as well 
    public UserListListener(Server networking) { 
     this.m_networking = networking; 
    } 

    public String getSelectedUser() { 
     //determine the selected user on the JList 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     String command = e.getActionCommand(); 
     if (command.equals("kick")) { 

      //so here, you determine the user that was selected and tell the server to kick him 
      server.kick(getSelectedUser()); 
     } 
    } 
} 

편집 : 서버 클래스에서

public void kick(String username) { 
    for(int i = 0 ; i < MAX_CLIENTS ; i++) { 
     if (this.m_clients[ i ].getUsername().equals(username) { 
      this.m_clients[ i ].close(); 
      this.m_clients[ i ] = null; 
     } 
    } 
} 
+0

아주 잘 작동하는 것 같습니다. 나는 이것을 밖으로 시험 할 것이다 :) 고마워. – user3130731

+0

아주 잘 작동합니다! 그러나 나는 한 가지 질문이있다. 내 서버 제어판을 통해 사용자를 차버리는 중입니다. 내 제어판에서 JList를 사용하여 현재 로그인 한 사용자 중 하나를 선택할 수 있습니다. (플레이어가 로그인하면 클라이언트에서 사용자 이름을 얻습니다.) Server 클래스를 사용하여 kick 명령을 통해 플레이어를 걷어차는 방법은 무엇입니까? 클래스를 사용하여 업데이트 된 코드는 다음과 같습니다. http://pastebin.com/ZS7SM1XB 그런데 String 사용자는 ControlPanel 클래스에서 JList의 선택된 사용자로 전송됩니다. 당신의 도움을 주셔서 감사합니다. – user3130731

+0

제어판에 어떤 종류의 리스너 (예 : ActionListener)가 있다고 가정합니다. 내 방법은 Server 개체를 ActionListener 생성자에 전달하는 것입니다. 그런 다음 ActionListener에 서버에 대한 참조가 있습니다. ActionListener에서 "kick"을 클릭하면 ActionListener가 이벤트를 가져오고 actionPerformed() 메서드가 실행됩니다. actionPerformed() 메소드에서 ActionListener에 서버에 대한 참조가 있으므로 server.kick()을 호출 할 수 있습니다. (위 편집을 참조하십시오.) – user2570465

관련 문제