BroadCastingServer.java
package prac;
import java.awt.Frame;
import java.awt.TextArea;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
//클라이언트의 접속을 받아 모든 클라이언트에게 데이터르 전송시키는 serverThread객체를 생성
public class BroadCastingServer {
//서버의 폼을 구성하는 Component
private Frame f;
private TextArea state;
//클라이언트와 소켓을 형성하기 위한 클라스 선언
private ServerSocket server;
private Socket socket;
//데이터를 주고 받을 수 있도록 Thread로 구현한 클래스 선언
private serverThread st;
// 생성자, GUI폼 구성
public BroadCastingServer(){
f=new Frame("Server");
state=new TextArea("",30,50,TextArea.SCROLLBARS_NONE);
state.setEditable(false);
f.add(state,"Center");
f.setSize(300, 400);
f.setLocation(300, 300);
f.setResizable(false);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
} // 생성자 end
// 서버를 실행시키는 메소드
public void startServer(){
try {
//대표 포트 6666을 가지고 클라이언트의 접속을 기다리는 ServerSocket 객체 생성
server=new ServerSocket(6666);
while (true) {
//클라이언트와 접속을 성공시켜 소켓 생성
socket=server.accept();
//스트림 생성
DataInputStream dis=new DataInputStream(socket.getInputStream());
DataOutputStream dos=new DataOutputStream(socket.getOutputStream());
//클라이언트가 전송하는 ID값을 받아들임
String name =dis.readUTF();
//broadcasting을 해주는 serverThread객체 생성
st=new serverThread(socket, state, dis, dos, name);
Thread t=new Thread(st);
t.start();
}// while end
} catch (IOException ioe) {
System.out.println(ioe.getMessage());
}
} //startServer(0 end
public static void main(String[] args){
BroadCastingServer ser =new BroadCastingServer();
ser.startServer();
}
}
--------------------------------------------------------------------------
serverThread.java
package prac;
import java.awt.TextArea;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;
//Thread를 이용해 모든 클라이언트에게 데이터를 전송해주는 broadcasting을 구현한 클래스
public class serverThread implements Runnable{
// 접속한 클라이언트를 저장하는 vector 객체 생성
private static Vector list =new Vector();
// BroadCastingServer가 넘겨주는 argument를 저장하기 위한 멤버 변수 선언
private Socket socket;
private TextArea state;
private DataInputStream dis;
private DataOutputStream dos;
// 사용자의 대화명을 저장하는 변수 선언
String talkName;
//생성자
// BroadCastingServer에서 넘겨주는 argument를 멤버변수에 할당
public serverThread(Socket socket, TextArea state, DataInputStream dis, DataOutputStream dos, String talkName) throws IOException{
this.socket=socket;
this.state=state;
this.dis=dis;
this.dos=dos;
this.talkName=talkName;
}
@Override
public void run() {
// 서버의 TextArea에 현재 접속한 클라이언트를 출력
state.append(talkName + " 님이 입장하셨습니다\n");
// 모든 클라이언트들에게 현재 접속한 사용자를 알려줌
compareState("LogOut/" + talkName + "님이 입장하셨습니다");
try {
// 현재 접속한 사용자를 Vector에 추가
list.addElement(this);
while (true) {
String msg=dis.readUTF();
compareState(msg);
} // while end
} catch (IOException ioe) {
// 소켓이 끊어지거나, 스트림이 해체 되었을 경우
// exception이 발생한 경우는 퇴장한 경우이므로
state.append(talkName + "님이 퇴장 하였습니다.\n");
compareState("LogOut/" + talkName + "님이 퇴장 하였습니다.\n");
// Vector 에서 현재 Exception이 난 Object를 제거
list.removeElement(this);
try {
socket.close();
} catch (Exception e) {
System.out.println("소켓 닫는 도중 에러 발생 ");
}
} // catch end
} //run() end
// 현재 Login 을 하려고 하는 건지, 대화 내용을 보내는 중인지를 판단하기 위해서 선언한 method
public void compareState(String message){
StringTokenizer st =new StringTokenizer(message,"/");
String protocol=st.nextToken(); //Login, Logout Message
String msg=st.nextToken();
System.out.println(msg);
if(protocol.equals("Login")|| protocol.equals("LogOut")){
broadCasting("NONE",msg);
}else{
broadCasting(talkName, msg);
}
} //compareState() end
// 현재서버에 접속한 모든 클라이언트에게 메세지를 보내주는 method
//BroadCasting 기능이 먼저 완료되어 채팅글이 꼬이지 않도록 한다.
public void broadCasting (String talkName, String message){
synchronized (list) {
Enumeration e =list.elements();
while(e.hasMoreElements()){
serverThread temp=(serverThread)e.nextElement();
try {
temp.dos.writeUTF(talkName);
temp.dos.writeUTF(message);
} catch (IOException ioe) {
System.out.println(ioe);
}
} // while end
} //synchronized() end
} //broadCasting
}
-------------------------------------------------------------------------------------
BroadCastingClient.java
package prac;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class BroadCastingClient implements Runnable, ActionListener{
// 클라이언트의 폼을 구성하는 component
Frame first, second;
Panel p;
TextField ipField;
TextField idField;
Button connection;
TextArea talkScreen;
TextField tf;
// 서버와의 접속을 위한 socket 객체 선언
Socket socket;
// 스트림 클래스 선언
DataInputStream dis;
DataOutputStream dos;
Thread listen;
// 생성자, 클라이언트 GUI폼을 구성
public BroadCastingClient(){
first=new Frame("LOGIN");
// second=new Frame("접속 성공");
connection =new Button("Connect");
// Server 의 IP와 대화명을 받아들이는 TextField를 생성
ipField=new TextField(15);
idField=new TextField(15);
// Label을 붙인 Panel
Panel p1=new Panel();
p1.setLayout(new GridLayout(2,1,0,10));
p1.add(new Label("Server", Label.CENTER));
p1.add(new Label("ID",Label.CENTER));
// TextField를 붙인 Panel
Panel p2=new Panel();
p2.setLayout(new GridLayout(2,1,0,10));
p2.add(ipField);
p2.add(idField);
Panel p3=new Panel();
p3.add(p1);
p3.add(p2);
// 연결 시도 프레임 구성
first.setLayout(new BorderLayout(0,10));
first.add(p3,"Center");
first.add(connection, "South");
// Window의 종료 이벤트 처리
first.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
first.setSize(300, 150);
first.setLocation(300, 300);
first.setVisible(true);
// 버튼에 ActionEvent를 등록 시킴
connection.addActionListener(this);
} // 생성자 end
// 로그인 프레임이 종료한 후에 대화를 나눌 수 있는 GUI폼을 구성해 주는 메소드
public void secondFrame(String id){
second=new Frame(id+ " : Client");
tf=new TextField(15);
talkScreen = new TextArea("",30,50,TextArea.SCROLLBARS_NONE);
talkScreen.setEditable(false);
second.add("Center", talkScreen);
second.add("South", tf);
second.setSize(320, 420);
second.setVisible(true);
// Window의 종료 이벤트 처리
second.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
tf.addActionListener(this);
} // secondFrame() end
// Server 와의 연결을 시도하는 메소드
public void connectServer(String id,String address, int port){
try {
// 서버와의 연결
socket=new Socket(address,port);
// 현재 접속한 서버와 스트림 형성
dis =new DataInputStream(socket.getInputStream());
dos=new DataOutputStream(socket.getOutputStream());
dos.writeUTF(id);
} catch (IOException ioe) {
System.out.println("서버가 없습니다");
System.exit(0);
}
// 클라이언트 자체도 Thread구동 시킴
listen=new Thread(this);
listen.start(); // run() 메소드 호출
} // connectServer() end
@Override
// 텍스트 필드에서 데이터를 입력하고, 엔터를 치는 ActionEvent 처리
public void actionPerformed(ActionEvent av) {
// TextField에서 Event가 발생 했을 경우 (TextField에 값 입력 후 엔터키)
if(av.getSource()==tf){ // 두번째 화면
try {
// 서버측으로 데이터 전송
dos.writeUTF("Message/" +tf.getText());
tf.setText(" ");
} catch (IOException ioe) {
System.out.println(ioe);
}
// Button에서 Event가 발생 했을 경우 (Button 클릭)
}else if(av.getSource()==connection){
String address=ipField.getText();
String id=idField.getText();
first.setVisible(false);
first.dispose();
secondFrame(id);
connectServer(id, address, 6666);
}
}
@Override
public void run() {
// 서버로부터 받은 데이터를 자신의 TextArea에 출력 시킴
try {
while (true) { // serverThread.java 파일 99,100 라인
String id=dis.readUTF(); //대화명(talkName)을 읽음
String line = dis.readUTF(); // message를 읽음
if(id.equals("NONE")){ // 입장과 퇴장
talkScreen.append(line +"\n");
}else{
talkScreen.append("["+id+"]:"+line+"\n");
}
}
} catch (IOException ioe) {
talkScreen.append("서버에서 데이터를 읽는 중 에러 발생");
try {
Thread.sleep(1000); // 1초동안 block상태로 만듬
} catch (InterruptedException e) {
}
System.exit(0);
}
} // catch end
public static void main(String[] args){
BroadCastingClient bcc=new BroadCastingClient();
}
}
'Java' 카테고리의 다른 글
DataInputStream / DataOutputStream (0) | 2014.12.25 |
---|---|
Finding IP using the domain name (0) | 2014.12.25 |
class StringBuilder (0) | 2014.12.24 |
Runtime.getRuntime().exec() (0) | 2014.12.24 |
open web browser (0) | 2014.12.23 |