E001 // 클라이언트에서 연결 요청하면 서버는 네트워크 연결 초기화
E002 // 서버 데이터가 도착할 때까지 계속 대기
E003 // (수신전용스레드와 별개로) 메인 스레드 N41 이후 실행중
E004 // 대화를 입력할 때까지 계속 대기
E005 // '안녕하세요' 입력
E006 // 서버로 데이터([CHAT] [클라이언트2]안녕하세요) 전송
E007 // 서버에서 보낸 데이터([CHAT] [클라이언트1]반갑습니다) 도착
E008 // 프로그램 닫기(우측상단 X) 선택
E009 // 메인스레드와 수신전용스레드가 모두 종료하여 프로그램 종료
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import chat.ChatNetworkPanel;
public class ChatGUIClient
{
1 public static void main( String[] args ) {
String serverIP = "localhost";
2 ChatNetworkPanel panel =
3 new ChatNetworkPanel( serverIP );
JFrame frame = new JFrame( "채팅(클라이언트)" );
frame.getContentPane().add( panel );
frame.addWindowListener( new WindowAdapter() {
Wb public void windowClosing( WindowEvent event ) {
W1 panel.close();
We }
} );
frame.setPreferredSize( new Dimension( 320, 445 ) );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.pack();
frame.setVisible(true);
4 }
}
package chat;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import network.Network;
public class ChatNetworkPanel extends JPanel implements ActionListener, Runnable
{
private JTextArea chatWindow;
private JTextField inputField;
private Network network;
private String id;
private final String header = "[CHAT] ";
CN1b public ChatNetworkPanel() {
chatWindow = new JTextArea();
chatWindow.setBackground( Color.lightGray );
chatWindow.setEditable( false );
chatWindow.setLineWrap( true );
JScrollPane scroll = new JScrollPane( chatWindow );
scroll.setPreferredSize( new Dimension( 290, 360 ) );
add( scroll );
inputField = new JTextField();
inputField.setPreferredSize( new Dimension( 290, 30 ) );
inputField.addActionListener( this );
inputField.requestFocus();
add( inputField );
setVisible( true );
CN1e }
CN2b public ChatNetworkPanel( String serverIP ) {
CN21 this();
CN22 network =
CN23 new Network();
CN24 network.connectAsClient( serverIP, this );
id = "[" + JOptionPane.showInputDialog( this, "아이디를 입력해주세요.", "아이디" ) + "]";
network.write( header + id + "님이 들어오셨습니다" );
CN2e }
@Override
CN3b public void actionPerformed( ActionEvent event ) {
String message = inputField.getText();
CN31 network.write( header + id + message );
inputField.setText( "" );
CN3e }
@Override
CN4b public void run() {
CN41 for ( String message = null; ( message =
CN42 network.read() )
!= null; ) {
if ( !message.contains( header ) )
continue;
CN43 chatWindow.append( message.substring( header.length() ) + "\n" );
chatWindow.setCaretPosition( chatWindow.getText().length() );
CN44 }
CN4e }
CN5b public void close() {
network.write( header + " " + id + "님이 나가셨습니다" );
CN51 network.close();
CN5e }
}
package network;
import java.io.*;
import java.net.*;
public class Network
{
public static final int serverPort = 7700;
protected ServerSocket serverSocket;
protected Socket socket;
private BufferedReader in;
private PrintWriter out;
private Thread waitForCounterpart;
N1b public Network() {
serverSocket = null;
socket = null;
in = null;
out = null;
waitForCounterpart = null;
N1e }
N2b public void connectAsServer( Runnable obj ) {
try {
serverSocket = new ServerSocket( serverPort );
N21 socket =
N22 serverSocket.accept();
N23 connectInOut( obj );
} catch ( Exception e ) {
e.printStackTrace();
}
N2e }
N3b public void connectAsClient( String serverIP, Runnable obj ) {
try {
N31 socket =
N32 new Socket( serverIP, serverPort );
N33 connectInOut( obj );
} catch ( Exception e ) {
e.printStackTrace();
}
N3e }
N4b public void connectInOut( Runnable obj ) {
try {
in = new BufferedReader( new InputStreamReader( socket.getInputStream() ));
out = new PrintWriter( socket.getOutputStream(), true );
waitForCounterpart = new Thread( obj );
N41 waitForCounterpart.start();
} catch ( Exception e ) {
e.printStackTrace();
}
N4e }
N5b public String read() {
try {
if ( this.isConnecting() == true )
N51 return
N52 in.readLine();
} catch ( Exception e ) {
e.printStackTrace();
}
return null;
N5e }
N6b public void write( String data ) {
try {
if ( this.isConnecting() == true )
N61 out.println( data );
} catch ( Exception e ) {
e.printStackTrace();
}
N6e }
public boolean isConnecting() {
if ( ( socket != null )
&& ( in != null )
&& ( out != null )
&& ( waitForCounterpart != null )
&& ( waitForCounterpart.getState() != Thread.State.TERMINATED ) )
return true;
else
return false;
}
N7b public void close() {
try {
if ( waitForCounterpart != null ) {
waitForCounterpart.interrupt();
waitForCounterpart = null;
}
if ( in != null ) {
in.close();
in=null;
}
if ( out != null ) {
out.flush();
out.close();
out = null;
}
if ( socket != null ) {
socket.close();
socket = null;
}
if ( serverSocket != null ) {
serverSocket.close();
serverSocket = null;
}
} catch ( Exception e ) {
e.printStackTrace();
}
N7e }
}