2013-04-16 4 views
0

채팅 서버를 만들고 있는데 하나 이상의 연결을 설정할 수 없습니다. 이는 소켓이 하나뿐이기 때문입니다. 스레드가 한 번에 둘 이상의 소켓 연결을 처리 할 수 ​​있지만 각 클라이언트는 자신의 소켓을 가져야한다는 것을 읽었습니다. 벽 콘센트처럼. 플러그 당 1 개의 콘센트가 있어야합니다. 어떻게 각 클라이언트가 서버와 통신하는 데 사용할 소켓을 만드나요? 나는 너희들을 도울 수있는 약간의 코드를 제공 할 것이다. 단일 소켓 (연결)이 허용되는 곳입니다. 여기Java 사용자가 연결된 사용자 당 새 소켓을 생성하는 데 도움이됩니다.

private void waitForConnection() throws IOException 
{ 
    connection = server.accept(); 
    showMessage("\nNow connected to " + connection.getInetAddress().toString()); 
    clientCount += 1; 
} 

코드는 서버 시작시 호출되는 경우입니다 :

public void startRunning() 
{ 
    try 
    { 
    server = new ServerSocket(1337, 10); 
    while(true) 
    { 
     try 
     { 
      showMessage("Waiting For a Player To Connect..."); 
      waitForConnection(); 
      setupStreams(); 
      whileChatting(); 

     } 
     catch(EOFException eofException) 
     { 
      showMessage("\n Server ended the connection! "); 
     } 
     finally 
     { 
      closeConnections(); 
     } 
    } 
    } 
    catch(IOException ioException) 
    { 
    ioException.printStackTrace(); 
    } 
} 

지금이 코드는 첫 번째 연결된 클라이언트에 대해 완벽하게 작동합니다. 다른 모든 사람들은 간단히 연결할 수 없습니다. 답변을 제출 한 모든 사람들에게 미리 감사드립니다.

답변

0

코드의 전체 구조는 잘못된 것입니다 :이 필요한 일을 할 수 없습니다

waitForConnection(); 
setupStreams(); 
whileChatting(); 

. 루프는 아무것도하지 않고 연결을 받아들이고 그 소켓을 통해 모든 I/O를 처리하는 새로운 스레드를 시작해야합니다. Java 자습서의 Custom Networking 섹션을 참조하십시오.

1

스레드는 항상 socket.accept()으로 실행해야합니다. 즉 :

  • 당신이 (socket.accept() 통해) 클라이언트를받을 때마다, 당신은
      새로운 Thread를 시작
    • 한다, 지금 해당 클라이언트를 돌봐에서 해당됩니다. (나는 Thread 연장 클래스 ClientNanny라고 부를 것이다.);
    • 그리고 나서 socket.accept()으로 다시 돌아 오십시오.

이것은 당신의 waitForConnection() 방법과 같이 갈까요 것입니다 :

당신은 통지를하지 않은 경우
private List<ClientNanny> clients = new ArrayList<ClientNanny>(); 

private void waitForConnection() throws IOException 
{ 
    while (true) { /* or some other condition you wish */ 
     connection = server.accept(); /* will wait here */ 
     /* this code is executed when a client connects... */ 

     showMessage("\nNow connected to " 
             + connection.getInetAddress().toString()); 

     ClientNanny nanny = new ClientNanny(connection); /* call a nanny to take 
                  care of it */ 
     clients.add(nanny); /* make sure you keep a ref to it, just in case */ 
     nanny.start(); /* tell nanny to get to work as an independent thread */ 
     clientCount += 1; /* you dont need this: use clients.size() now */ 
    } 
} 

, ClientNanny는해야 뭔가 같은 : 이제

class ClientNanny extends Thread { 
    ClientNanny(Socket baby) { 
     this.myBaby = baby; 
    } 
    @Override 
    public void run() { 
     bed.put(myBaby); /* and probably other commands :) */ 
    } 
} 

, 당신을 아래에 강조 표시된 코드가 표시됩니다.

try 
{ 
    showMessage("Waiting For a Player To Connect..."); 
    waitForConnection(); 
    setupStreams(); /* <--------- THIS LINE! HI! I'M A HIGHLIGHT! */ 
    whileChatting(); /* <--------- THIS LINE! HI! I'M A HIGHLIGHT TOO! */ 
} 

내가 제안한대로 waitForConnection()을 변경하면 실행되지 않습니다 (waitForConnection()while(true) 루프 내에서 계속 롤업 됨). 어쩌면 당신은 socket.accept()을 그 자체의 스레드에 넣을 수 있습니다 ... 어쨌든, 지금부터 할 수 있다고 믿습니다. 이 문제를 설명하는 가장 쉬운 방법이기 때문에 최종 포인터로

추신 :이 솔루션은 위의 (그 문제 또는 new ClientNanny()) new Thread()을 사용합니다. 매우 최적의 솔루션은 ExecutorService (대략적으로 스레드 풀)을 사용하는 것이고 this answer에 곧 지적됩니다.

0

귀하의 소켓 코드는이 의사 코드처럼 보일 것입니다 :

입니다
create server socket 
while true (or quit received) { 
    accept connection 
    spawn thread to handle communication 
} 

, 각 연결에 대한 스레드를 생성해야합니다. 그런 다음 각 스레드는 주 스레드를 들고 있기보다는 whileChatting()을 수행 할 수 있습니다.

예 :

while (true) { 
    try { 
     // listen for client connections 
     Socket s = svr.accept(); 

     // start a separate thread to handle this client's communications 
     new ChatClientHandler(s).start(); 
    } 
    catch (IOException e) { 
     // print out the error, but continue! 
     System.err.println(e); 
    } 
}