채팅앱

구현할 내용
채팅 서버와 채팅 클라이언트가 일대일로 채팅하는 프로그램
1) 도스 콘솔에서 키보드로 메시지를 입력해서 보낸다. (일대일 채팅) --> Thread를 이용해서 동시에 들을 수 있게 해줌
2) GUI CHAT 구현 (멀티 채팅)

1)
Server

package net.day02;

import java.net.*;
import java.io.*;

public class ChatServer {

	private ServerSocket server;
	private Socket sock;
	private final int port=33333;
	private BufferedReader key, in;
	private BufferedWriter out;
	public ChatServer(){
		try {
			System.out.println("서버 시작 되었습니다.");
			server = new ServerSocket(port);
			sock=server.accept();
			InetAddress ia= sock.getInetAddress();
			String cip = ia.getHostAddress();
			System.out.println("##클["+cip+"]님이 접속##");
			
			//1. 키보드 입력 스트림 생성
			key = new BufferedReader(new InputStreamReader(System.in));
			//2. 클에게 메시지를 보낼 출력 스트림 얻기
			out = new BufferedWriter(new OutputStreamWriter(
					sock.getOutputStream()));
			//3. 클이 보내오는 메시지를 듣고 콘솔에 출려하는 스레드를 동작
			ChatListner listner = new ChatListner();
			listner.start();
			
			//4. 키보드 입력하여 클에게 메시지를 보낸다.
			String myMsg="";
			while((myMsg=key.readLine())!=null) {
				out.write(myMsg);
				out.newLine();
				out.flush();
			}
		} catch (IOException e) {
			System.out.println("예외 "+e.getMessage());
		}
	}//생성자------------
	
	class ChatListner extends Thread{
		@Override
		public void run() {
			//클이 보내오는 메시지를 계속 듣고 자기 콘솔에 출력한다.
			try {
				in = new BufferedReader(new InputStreamReader(
						sock.getInputStream()));
				String cMsg="";
				while((cMsg=in.readLine())!=null) {
					System.out.println("From Client>>"+cMsg);
				}
			} catch (IOException e) {
				e.printStackTrace();
				System.out.println("예외: "+e.getMessage());
				close();
			}		
		}
	}//run()---------
	
	private void close() {
		try {
			if(in!=null)	in.close();
			if(out!=null)	out.close();
			if(key!=null)	key.close();
			if(sock!=null)	sock.close();
			if(server!=null)server.close();
		} catch (IOException e) {
			System.out.println("예외: "+e.getMessage());
		}
	}

	public static void main(String[] args) {
		new ChatServer();
	}

}

Client

package net.day02;

import java.net.*;
import java.io.*;
import javax.swing.*;

public class ChatClient implements Runnable{
	
	private String ip="127.0.0.1";
	private final int port = 33333;
	private Socket sock;
	private BufferedReader key, in;
	private BufferedWriter out;
	
	public ChatClient(String ip) {
		if(ip!=null) this.ip=ip;
		
		try {
			//1. 소켓생성
			sock = new Socket(ip,port);
			System.out.println("서버에 접속 되었습니다.");
			//2.키보드 입력 스트림 생성
			key = new BufferedReader(new InputStreamReader(System.in));
			//3. 서버에 출력할 스트림 얻기 => 필터링
			out = new BufferedWriter(new OutputStreamWriter(
					sock.getOutputStream()));
			//4. 서버가 보내오는 메시지를 들을 스레드 생성 및 동작
			Thread tr =new Thread(this);
			tr.start();
			//5. 키보드 입력하여 메시지를 서버에 보낸다.
			String myMsg="";
			while((myMsg=key.readLine())!=null) {
				out.write(myMsg);
				out.newLine();
				out.flush();
			}
		} catch (UnknownHostException e) {
			System.out.println("예외: "+e.getMessage());
		} catch (IOException e) {
			System.out.println("예외: "+e.getMessage());
		}
	}//생성자 ㅡㅡㅡㅡㅡㅡㅡㅡㅡ
	
	@Override
	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(
					sock.getInputStream()));
			String sMsg="";
			while((sMsg=in.readLine())!=null) {
				System.out.println("From Server>>"+sMsg);
			}
		} catch (IOException e) {
			System.out.println("예외: "+e.getMessage());
			close();
		}
	}
	private void close() {
		try {
			if(in!=null)	in.close();
			if(out!=null)	out.close();
			if(key!=null)	key.close();
			if(sock!=null)	sock.close();
		} catch (IOException e) {
			System.out.println("예외: "+e.getMessage());
		}
	}
	
	public static void main(String[] args) {
		String ip = JOptionPane.showInputDialog("접속할 서버에 ip주소를 입력하세요");
		ChatClient chat = new ChatClient(ip);
	}
}

2) GUI
Server

package net.day02;

import java.net.*;
import java.io.*;
import java.util.*;

public class ChatGuiServer {
	private ServerSocket server;
	Vector<ChatGuiHandler> v = new Vector<ChatGuiHandler>();
	
	public ChatGuiServer(final int port) {
		try {
			server = new ServerSocket(port);
			System.out.println("##ChatGuiServer Ready...##");
			while(true) {
				Socket sock = server.accept();
				System.out.println("##"+sock.getInetAddress()+"가 접속##");
				//통신 담당 스레드 생성
				ChatGuiHandler chat = new ChatGuiHandler(this,sock);
				//벡터에 저장
				v.add(chat);
				chat.start();//스레드 동작
				//
			}
		} catch (IOException e) {
			System.out.println("예외: "+e.getMessage());
		}
		
	}

	public static void main(String[] args) {
		new ChatGuiServer(7788);
	}

}


Client

package net.day02;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;

public class ChatGuiClient extends JFrame implements Runnable{

	JPanel p = new JPanel(new BorderLayout());
	JTextField tfHost, tfInput;
	JTextArea ta;
	boolean isCon=false;//서버에 접속하면 true,아니면 false
	Socket sock;
	ObjectInputStream in;
	ObjectOutputStream out;
	String nick;
	public ChatGuiClient() {
		super("::ChatGuiClient::");
		Container cp = getContentPane();
		cp.add(p,"Center");
		p.setBackground(Color.white);
		
		tfHost=new JTextField("192.168.0.183");
		p.add(tfHost,"North");
		tfHost.setBorder(new TitledBorder("Host"));
		
		ta=new JTextArea();
		p.add(new JScrollPane(ta), "Center");
		ta.setBorder(new LineBorder(Color.magenta,3));
		ta.setEditable(false);
		
		tfInput = new JTextField();
		p.add(tfInput,"South");
		tfInput.setBorder(new TitledBorder("대화명을 입력하세요"));
		
		
		//이벤트처리
		tfInput.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(!isCon) {
					connect();
				}else {//연결했다면
					sendMessage();
				}
			}
		});
		
		this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		//창닫기 이벤트 처리
		this.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				if(isCon) {
					try {
						out.writeUTF("exit#["+nick+"]님이 퇴장합니다.");
						out.flush();
						isCon=false;
						closeAll();
						System.exit(0);
					} catch (IOException e1) {
						System.out.println("퇴장 중 예외() : "+e1.getMessage());
					}
				}
			}
		});
	}//생성자------------
	public void closeAll() throws IOException{
		if(in!=null) in.close();
		if(out!=null) out.close();
		if(sock!=null)	sock.close();
	}
	@Override
	public void run() {
		//서버쪽에서 보내오는 메시지를 계속 듣고 ta에 출력을 해준다.
		while(isCon) {
			try {
				String msg = in.readUTF();
				ta.append(msg+"\r\n");
			} catch (IOException e) {
				System.out.println("Client run()에러: "+e.getMessage());
			}
		}
	}
	
	private void sendMessage() {
		String msg = tfInput.getText();
		try {
			//대화 메시지를 서버에 보낸다.
			out.writeUTF(msg);
			out.flush();
			tfInput.setText("");
		} catch (IOException e) {
			System.out.println("예외: "+e.getMessage());
		}
	}

	private void connect() {
		//1.접속할 서버의 ip주소 얻기
		String ip = tfHost.getText();
		//2.대화명 얻기
		nick=tfInput.getText();
		//3.유효성 체크
		if(ip==null||ip.trim().isEmpty()) {
			showMsg("접속할 서버의 IP주소를 입력");
			tfHost.requestFocus();
			return;
		}
		if(nick==null||nick.trim().isEmpty()) {
			showMsg("대화명을 입력");
			tfInput.requestFocus();
			return;
		}
		//4.소켓 생성후 스트림 얻기
		try {
			sock= new Socket(ip,7788);
			in = new ObjectInputStream(sock.getInputStream());
			out = new ObjectOutputStream(sock.getOutputStream());
			ta.setText("##서버에 접속["+ip+"]##");
			setTitle(nick+"님의 대화창");
			//접속하자마자 대화명을 보낸다.
			out.writeUTF(nick);
			out.flush();
			isCon=true;
			tfInput.setText("");
			tfInput.setBorder(new TitledBorder("::대화내용 입력::"));
			//스레드 동작
			Thread listener = new Thread(this);
			listener.start();
		} catch (UnknownHostException e) {
			System.out.println("Client 예외: "+e.getMessage());
		} catch (IOException e) {
			System.out.println("Client 예외: "+e.getMessage());
		}
		
		//5.대화명 서버에 보내주기
	}
	public void showMsg(String msg) {
		JOptionPane.showMessageDialog(this, msg);
	}

	public static void main(String[] args) {
		ChatGuiClient cg = new ChatGuiClient();
		cg.setSize(500,500);
		cg.setVisible(true);
	}

}


Handler

package net.day02;

import java.net.*;
import java.io.*;
import java.util.*;

public class ChatGuiHandler extends Thread{
	private ChatGuiServer server;
	private Socket sock;
			ObjectOutputStream out;
			ObjectInputStream in;
	private String nick;//대화명
	public ChatGuiHandler(ChatGuiServer server, Socket sock) {
		this.server=server;
		this.sock=sock;
		//스트림 연결
		try {
			out= new ObjectOutputStream(sock.getOutputStream());
			in = new ObjectInputStream(sock.getInputStream());
		} catch (IOException e) {
			System.out.println("예외2: "+e.getMessage());
		}
	}
	@Override
	public void run() {
		//클이 접속하면서 자신의 대화명을 먼저 보낼 예정..
		try {
			nick=in.readUTF();
			System.out.println("대화명: "+nick+"님이 입장..");
			//입장한 사람들에게 방금 입장한 사람의 대화명을 보내준다.
			broadcast("##["+nick+"]님이 입장##");
			while(true) {
				//클이 보내오는 메시지를 계속 듣는다.
				String cMsg=in.readUTF();
				if(cMsg.startsWith("exit#")) {
					//클이 퇴장 의사를 보내왔다면
					broadcast(nick+"님이 퇴장");
					this.server.v.remove(this);
					closeAll();
					return;
				}else {
					broadcast(nick+">>"+cMsg);
				}
			}
		} catch (IOException e) {
			System.out.println("예외2: "+e.getMessage());
		}
	}
	public void closeAll() throws IOException{
		if(out!=null)	out.close();
		if(in!=null)	in.close();
		if(sock!=null)	sock.close();		
	}
	/*모든 입장한 클에게 메시지를 보내는 메소드*/
	private synchronized void broadcast(String msg) {
		//모든 클과 통신하는 스레드를 저장하고 있는 벡터에서 ChatGuiHandler를 꺼내서
		Enumeration<ChatGuiHandler> en= this.server.v.elements();
		while(en.hasMoreElements()) {
			ChatGuiHandler c = en.nextElement();
			try {
				c.out.writeUTF(msg);
				c.out.flush();
			} catch (IOException e) {
				System.out.println("broadcast()예외: "+e.getMessage()+c);
//				this.server.v.removeElement(c);
			}
		}
	}
}

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

실습

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Movie</title>
    <style>
        body{
            background-color: skyblue;
            color : white;
        }
        button{
            padding:5px;
            height: 35px;
            width: 100px;
            margin:2px;
        }
        div#movies{
            width:90%;
            margin: 50px auto;/*상하 (50) 좌우(auto)*/
            text-align: center;
        }
        #movies img{
            width:125px;
            height: 200px;
            border : 1px solid white;
            padding: 1px;
        }
    </style>
</head>
<body>
    <button id="btnCurrent" onclick="fbtnCurrent()">현재 상영작</button>
    <button id="btnPlay" onclick="go()">▶</button>
    <button id="btnStop" onclick="stop()">■</button>
    <div id="movies">
        <!-- <img src='images/a.jpg'> -->
    </div>

    <script>
        //1현재 상영중인 영화 이미지들을 배열에 저장
        var imgList = ["<img src='images/a.jpg'>",
        "<img src='images/b.jpg'>","<img src='images/c.jpg'>",
        "<img src='images/d.jpg'>","<img src='images/e.jpg'>"];
        //2현재 상영작 버튼을 누르면 배열에 저장한 영화 이미지를
        //id가 movies인 곳에 나타나도록 처리
        var c=0;
        var pl = 1;
        var w=null;
        function fbtnCurrent(){
            var obj = document.getElementById("movies");
            var str="";
            for(var i=0;i<imgList.length;i++){
                str+=imgList[(i)%5];
            }
            obj.innerHTML=str;
            obj.style.marginLeft=c+"px";
            c+=pl;
            if(c==300||c==-100){
                pl=-pl
            }
        }
        //3▶버튼을 누르면 영화 이미지들이 오른족으로 이동
        //오른쪽 끝으로 다 이동하면 다시 왼쪽으로 이동
        function go(){
            if(w==null){
                w = setInterval(fbtnCurrent,5);
            }
        }
        //4■멈추기
        function stop(){
            clearInterval(w);
            w=null;
        }
    </script>
</body>
</html>

+ Recent posts