E001 // 클라이언트에서 연결 요청할 때까지 계속 대기
E002 // [TV]에서 연결 요청하면 서버는 네트워크 연결 초기화
E003 // 클라이언트 데이터가 도착할 때까지 계속 대기
E004 // (수신전용스레드와 별개로) 메인 스레드 S16 이후 실행중
E005 // [리모컨]에서 연결 요청하면 서버는 네트워크 연결 초기화
E006 // [리모컨]에서 보낸 데이터([RMTC] [리모컨] POWER)가 도착
E007 // 데이터([RMTC] [리모컨]POWER)를 [TV]에게 전송
E008 // 데이터([RMTC] [리모컨]POWER)를 [리모컨]에게 전송
E009 // [리모컨]에서 보낸 데이터([RMTC] [리모컨] RIGHT)가 도착
E010 // 데이터([RMTC] [리모컨] RIGHT)를 [TV]에게 전송
E011 // 데이터([RMTC] [리모컨] RIGHT)를 [리모컨]에게 전송
// 파일명 : ./Chapter18/MultiClientServer_Main.java
import network.MultiClientServer;
// 멀티클라이언트 서버 Main 클래스
public class MultiClientServer_Main
{
1 public static void main( String[] args ) {
2 new MultiClientServer();
3 }
}
// 파일명 : ./src/network/MultiClientServer.java
package network;
import java.net.*;
import java.util.*;
// 멀티클라이언트 서버 클래스
public class MultiClientServer
{
private ServerSocket serverSocket;
private ArrayList<ThreadPerClient> clients;
// 멀티클라이언트 서버 초기화
S1b public MultiClientServer() {
try {
// 서버 소켓 연결
serverSocket = new ServerSocket( Network.serverPort );
clients = new ArrayList<ThreadPerClient>();
System.out.println( "[Server] 서버 대기중" );
// 각 클라이언트마다 반복
S11 while ( true ) {
// 네트워크 연결 활성화
S12 Socket socket =
S13 serverSocket.accept();
// 네트워크 입출력 초기화
S14 ThreadPerClient client =
S15 new ThreadPerClient( socket, clients );
clients.add( client );
// 클라이언트 전담 스레드 시작
S16 client.start();
S17 System.out.println( "[Server] 클라이언트 연결 : " + client );
}
} catch ( Exception e ) {
close();
e.printStackTrace();
}
S1e }
// 멀티클라이언트 서버 종료
public void close() {
try {
// 클라이언트 전담 스레드 전체 종료
for ( ThreadPerClient client : clients ) {
client.close();
client.interrupt();
clients.remove( client );
}
// 서버 소켓 종료
if ( serverSocket != null ) {
serverSocket.close();
serverSocket = null;
}
} catch ( Exception e ) {
e.printStackTrace();
}
}
}
// 파일명 : ./src/network/ThreadPerClient.java
package network;
import java.io.*;
import java.net.*;
import java.util.*;
// 클라이언트 전담 스레드
public class ThreadPerClient extends Thread
{
private Socket socket;
private BufferedReader in;
private PrintWriter out;
private ArrayList<ThreadPerClient> clients;
// 클라이언트 전담 스레드 초기화
C1b public ThreadPerClient( Socket socket, ArrayList<ThreadPerClient> clients ) {
super();
try {
// 네트워크 입출력 초기화
this.in = new BufferedReader( new InputStreamReader( socket.getInputStream() ) );
this.out = new PrintWriter( socket.getOutputStream(), true );
this.socket = socket;
this.clients = clients;
} catch ( Exception e ) {
e.printStackTrace();
}
C1e }
// 클라이언트 전담 스레드 시작
@Override
C2b public void run() {
try {
// 담당 클라이언트에서 보낸 데이터를 읽기
C21 for( String data = null; ( data =
C22 in.readLine() )
!= null; ) {
System.out.println("[Server] 데이터 도착 : " + this + " " + data );
// 전체 클라이언트에게 데이터를 보내기
C23 for( ThreadPerClient client : clients ) {
C24 client.write( data );
}
C25 }
} catch ( Exception e ) {
close();
e.printStackTrace();
}
C2e }
// 담당 클라이언트에게 데이터 보내기
C3b public void write( String data ) {
try {
// 담당 클라이언트와 네트워크 연결 종료시 데이터 전송 불가
if ( this.getState() == Thread.State.TERMINATED ) {
System.out.println( "[Server] 클라이언트 연결 해제 : " + this );
close();
}
// 담당 클라이언트와 네트워크 연결 유효시 데이터 전송
else if ( out != null ) {
System.out.println("[Server] 데이터 전송 : " + this + " " + data );
C31 out.println( data );
}
} catch ( Exception e ) {
e.printStackTrace();
}
C3e }
// 담당 클라이언트의 네트워크 종료
public void close() {
try {
if( socket != null ) {
socket.close();
socket = null;
}
if( in != null ) {
in.close();
in = null;
}
if( out != null ) {
out.close();
out = null;
}
} catch ( Exception e ) {
e.printStackTrace();
}
}
}