자바 웹 개발자가 될거야/JAVA

[JAVA] 소켓통신으로 1:1 채팅하기

whitz 2021. 12. 15. 12:04

< 소켓통신으로 1:1 채팅하기 >

 

- 선을 통해서 데이터가 들어감

- 자바에서 소켓이라는 라이브러리 제공 

- 포트번호에 따라 지정한 어플리케이션과 통신 

- 서버와 클라이언트 개념을 가짐

  · 클라이언트 : 요청하는 쪽

  · 서버 : 응답하는 쪽

- 서버부터 먼저 실행되고 클라이언트를 실행해야 함

  · 서버는 항상 켜져있는걸로 셋팅하겠다

 

- 서버소켓

  · 반드시 포트번호 기입 ( 10000번 이상을 권장 )

  · 무한으로 돌면서 클라이언트 접속을 기다림

  · accept() : 클라이언트를 받아옴

 

 

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerEx1 {

	public static void main(String[] args) {
		ServerSocket s = null; 
		try{ 
			s=new ServerSocket(54321); 
			System.out.println("Server Start.... " );
		
			while(true) { 
				Socket s1 = s.accept();
				InputStream is = s1.getInputStream(); 
				ObjectInputStream ois = new ObjectInputStream(is);
				System.out.println(ois.readObject());         
				System.out.println("accept  From: " + s1.getInetAddress().toString());
				OutputStream os = s1.getOutputStream();
				ObjectOutputStream oos = new ObjectOutputStream(os);
				oos.writeObject("내이름 Server");
				oos.close(); 
				ois.close();
				s1.close();
			}
		}catch(Exception e){ 
			System.out.println(e.getMessage());
		}

	}

}

 

- getInetAddress() : 클라이언트 주소를 가져옴

- 서버는 한번 실행시키고 수정하지 말기 그대로 냅두기

 

 

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;

public class ClientEx1 {

	public static void main(String[] args) {
		try{
			Socket s1 = new Socket("192.168.219.103", 54321);
			String str = "client message : hello"; 
			
			OutputStream out = s1.getOutputStream(); 
			ObjectOutputStream oos = new ObjectOutputStream(out); 
			oos.writeObject(str);     
			
			InputStream is = s1.getInputStream();
			ObjectInputStream ois = new ObjectInputStream(is);
			System.out.println("server >>> "+ois.readObject());         
			ois.close();
			is.close();         
		}catch(IOException e){
			e.printStackTrace(); 
		}catch(ClassNotFoundException e){ 
			e.printStackTrace(); 
		}

	}

}

 

- Socket(" ") 에 자신의 IP 주소 넣기 

- OutputStream : 보내고 / InputStream : 받기

- 동시에 보내고 받기하려면 스레드로 따로 만들어줘야함

 

서버Ex 실행
클라이언트Ex 실행

package Socket;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class SimpleServer extends JFrame implements ActionListener{
	JTextArea ta;
	JTextField tf;
	ServerSocket s;
	//Socket s1;
	DataInputStream din;
	DataOutputStream dout;
	
	boolean stop;
	
	SimpleServer(){
		//launchFrame();		
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		ta = new JTextArea();
		
		tf = new JTextField("입력해주세요");
		tf.addActionListener(this);
		
		setBackground(Color.LIGHT_GRAY);
		ta.setEditable(false);
		tf.setEnabled(false);
		add(new JScrollPane(ta), BorderLayout.CENTER);
		add(tf, BorderLayout.SOUTH);
		setSize(500, 300);
		setVisible(true);
		
		ta.append("서비스 준비중 ....\n");		
		
		service();
	}
	
	//public void launchFrame(){
		
	//}
	
	// 소켓을 작동시켜주는 서비스
	public void service() {
		
		try{
			s = new ServerSocket(5432);
			
			while(true){			
				//ta.append("클라이언트 접속대기중 ....\n");
			
				Socket s1 = s.accept();
				ta.append("클라이언트가 접속하였습니다. "+s1.getInetAddress()+"\n");
				
				tf.setEnabled(true);	
				//ChatThread t = new ChatThread();
				ChatThread t = new ChatThread(s1);
				t.start();			
				
			}
			
		}catch(IOException e ){
			ta.append(e.getMessage()+"2");
		}
	}
	

	@Override
	public void actionPerformed(ActionEvent arg0) {
		try{
			
			
				String msg = tf.getText();
				ta.append("me : "+msg+"\n");
				dout.writeUTF(msg);
				tf.setText("");
			
				if(msg.equals("exit")) {
					//ta.append("me : exit...\n");				
					stop = true;
					dout.close();
					//s1.close();
					s.close();
					System.exit(0);			
				}
			
			
		}catch(IOException e){
			ta.append("연결이 종료되었습니다1");
			tf.setEnabled(false);
			try{
				dout.close();
				//s1.close();
				
			}catch(Exception e1){}
			//ta.append(e.toString());
			
		}
		
	}

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

	}
	
	class ChatThread extends Thread{
		Socket s1;
		ChatThread(Socket s1){
			this.s1 = s1;
		}
	@Override
	public void run() {
		try{
			dout=new DataOutputStream(s1.getOutputStream());
			din = new DataInputStream(s1.getInputStream());
			
			dout.writeUTF("채팅서버에 접속하신것을 환영합니다 ");
			
			while(!stop) {
				
					String msg = din.readUTF();
					//if(msg.equals("exit")) stop=true;
					//else 
					ta.append(s1.getInetAddress()+" "+msg+"\n");
				
			}
			
			tf.setEnabled(false);
			din.close();
			s1.close();			
		}catch(IOException e){
			ta.append("연결이 종료되었습니다3\n");
			tf.setEnabled(false);
			try{
			  din.close();
			  s1.close();			
			  //ta.append(e.getMessage()+"  1 \n");
			}catch(Exception e1){}
		}
		
	}
	}	


}

 

package Socket;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class SimpleClient extends Thread implements ActionListener{
	
	JTextArea ta;
	JTextField tf, tf2;
	JDialog dialog;
	String host;
	
	Socket s1;
	DataInputStream din;
	DataOutputStream dout;
	boolean stop;
	
	SimpleClient(){
		launchFrame();		
	}
	

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

	}
	
	public void launchFrame(){		
		JFrame frame = new JFrame("yoon chatting");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		ta=new JTextArea();
		tf=new JTextField();
		tf.addActionListener(this);
		frame.setBackground(Color.lightGray);
		ta.setEditable(false);
		frame.add(new JScrollPane(ta), BorderLayout.CENTER);
		frame.add(tf, BorderLayout.SOUTH);
		
		frame.setSize(500, 300);
		frame.setVisible(true);
		
		dialog = new JDialog(frame,"Input IP Address ",true);
		JLabel label = new JLabel("Input IP Address ");
		tf2 = new JTextField("192.168.1.6",15);
		tf2.addActionListener(this);
		dialog.add(label, BorderLayout.NORTH);
		dialog.add(tf2, BorderLayout.CENTER);
		dialog.pack();
		dialog.setVisible(true);
		service();	
		
	}
	
	public void service(){
		try {
			s1 = new Socket(host,5432);
			din = new DataInputStream(s1.getInputStream());
			dout = new DataOutputStream(s1.getOutputStream());
			
			ta.append(host+" connect complete ...\n");
			this.start();
		}catch(IOException e){
			System.out.println("disconnect....");
			System.exit(0);
		}
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource() == tf){
			try{
				String msg = tf.getText();
				ta.append("me: "+msg+"\n");
				dout.writeUTF(s1.getInetAddress()+": "+msg);
				tf.setText("");
				if(msg.equals("exit")) {
					//dout.writeUTF(msg);
					//ta.append("bye");
					stop=true;
					dout.close();
					s1.close();
					System.exit(0);
				}else {

				}
			}catch(IOException e1){
				ta.append(e1.getMessage());
			}
		}else {
			host=tf2.getText().trim();
			if(host.equals("")) host="localhost";
			dialog.dispose();
		}
		
	}

	@Override
	public void run() {
		
		//System.out.println("Thread started ....");
		try{
			while(!stop){
				String msg = din.readUTF();
				ta.append("Server :"+msg+"\n");
				if(msg.equals("exit")) break;
			}
			din.close();
			s1.close();
			System.exit(0);
			
		}catch(IOException e){
			ta.append(e.getMessage());
		}		
		
	}
}

1:1 채팅 결과

 

- 클라이언트에서 exit 입력하면 종료됨