본문 바로가기

컴퓨터공학/Java

JAVA 소켓 네트워크 프로그래밍을 이용한 채팅 원리 이해

구성

Server

  • ChatServer
  • ClientManagerThread

 

Client

  • ChatClient
  • ReceiveThread
  • SendThread

 

 

그림판 신공을 이용하여 개요를 그려봤다..

과정을 예를 들어서 설명하자면..

어떤 클라이언트에서 send thread를 통해 데이터를 입력했다고 하자. 뭐 대충 1번 클라이언트가 그랬다고 치자.

그러면 1번 클라이언트 측 출력 소켓에 데이터가 가게 된다.

서버측은 1번 클라이언트에 할당되어있는 소켓에서 입력을 받게 된다.

입력을 받게되면, 서버는 다른 클라이언트 소켓에 데이터를 보낸다.

그러면 각 클라이언트 수신 소켓에서 입력을 받게 된다.

각 클라이언트 receive thread가 입력을 받고 입력받은 것을 각 클라이언트 콘솔에 표현한다.

이렇게 되면 1번 클라이언트가 서버에 메시지를 보낸것이 다른 클라이언트에 모두 표시된다.

 

윽.. 이게 뭔 말이야

 

 

 

그냥 소스코드를 보면서 이해하자..

 

소스코드

ChatServer

package server;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class ChatServer{
	
	public static ArrayList<PrintWriter> m_OutputList;
	
	public static void main(String[] args) {
		m_OutputList = new ArrayList<PrintWriter>();
		
		try {
			ServerSocket s_socket = new ServerSocket(8888);
			while(true){
				Socket c_socket = s_socket.accept();
				ClientManagerThread c_thread = new ClientManagerThread();
				
				m_OutputList.add(new PrintWriter(c_socket.getOutputStream()));
				
				c_thread.start();
			}
			
		}catch(IOException e) {
			e.printStackTrace();
			
		}
		
	}

}

 

ClientManagerThread

package server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ClientManagerThread extends Thread{
	private Socket m_socket;
	private String m_ID;
	
	@Override
	public void run() {
		super.run();
	try {
		BufferedReader tmpbuffer = new BufferedReader(new InputStreamReader(m_socket.getInputStream()));
		//외부에서 소켓으로 오는 입력값을 다루는 Inputstreamreader와 그걸 다루는 bufferedreader
		String text;
		//입력값 저장하는 변수
	
		while(true) {
			text = tmpbuffer.readLine(); //입력값을 변수에 저장한다.
			if(text == null) { //입력값이 없을 경우
				System.out.println(m_ID + "이 나갔습니다."); // 해당 클라이언트매니저에 표시
				for(int i = 0; i<ChatServer.m_OutputList.size(); ++i) { //다른 클라이언트매니저에도 표시할 수 있게 서버에 있는 소켓 출력 리스트에 접근하여 출력한다.
					ChatServer.m_OutputList.get(i).println(m_ID + "이 나갔습니다");
					ChatServer.m_OutputList.get(i).flush();
				}
				break;
			}
			
			String[] split = text.split("highkrs12345"); //클라이언트에서 접속하면 IDhighkrs12345라고 보내는데 그걸 쪼갠다
			if(split.length == 2 && split[0].equals("ID")) { // 입력값이 IDhighkrs12345라고 보낸게 맞는경우
				m_ID = split[1];
				System.out.println(m_ID + "이 입장하였습니다.");
				for(int i = 0; i<ChatServer.m_OutputList.size(); ++i) {
					ChatServer.m_OutputList.get(i).println(m_ID + "이 입장하였습니다.");
					ChatServer.m_OutputList.get(i).flush();
				}
				continue;
			}
			for(int i = 0; i<ChatServer.m_OutputList.size(); ++i) //클라이언트가 그냥 아무값을 입력했을 경우
			{
				ChatServer.m_OutputList.get(i).println(m_ID + ">" + text);
				ChatServer.m_OutputList.get(i).flush();
			}
			
			}		
			ChatServer.m_OutputList.remove(new PrintWriter(m_socket.getOutputStream()));
			m_socket.close();

	}catch(IOException e) {
		e.printStackTrace();
	}
	}
	
}

 

 

ChatClient

package client;

import java.io.IOException;
import java.net.Socket;
import java.rmi.UnknownHostException;

public class ChatClient {

	public static String userID;

	public static void main(String[] args) {

		try {
			Socket c_socket = new Socket("192.168.0.2",8888);
			
			ReceiveThread rec_thread = new ReceiveThread();
			rec_thread.setSocket(c_socket);
			
			SendThread send_thread = new SendThread();
			send_thread.setSocket(c_socket);
			
			send_thread.start();
			rec_thread.start();
			
		}catch(UnknownHostException e) {
			e.printStackTrace();
		}catch(IOException e) {
			e.printStackTrace();
		}
	}

}

 

 

ReceiveThread

package client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class ReceiveThread extends Thread{

	private Socket m_socket;
	
	@Override
	public void run() {
		super.run();
		try {
			BufferedReader tmpbuf = new BufferedReader(new InputStreamReader(m_socket.getInputStream()));
			
			String receiveString;
			String[] split;
			
			while(true) {
				receiveString = tmpbuf.readLine();
				split = receiveString.split(">");
				if(split.length >= 2 && split[0].equals(ChatClient.userID))
				{
					continue;
				}
				System.out.println(receiveString);
			}
		
		} catch(IOException e) {
			
		}
	}
	public void setSocket(Socket _socket) {
		m_socket = _socket;
	}
}

 

SendThread

package client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class SendThread extends Thread{

	private Socket m_socket;
	
	
	@Override
	public void run() {
		super.run();
		
		try {
			BufferedReader tmpbuf = new BufferedReader(new InputStreamReader(System.in));
			PrintWriter sendWriter = new PrintWriter(m_socket.getOutputStream());
			String sendString;
			
			System.out.println("사용할 ID를 입력하세요");
			ChatClient.userID = tmpbuf.readLine();
			sendWriter.println("IDhighkrs12345" + ChatClient.userID);
			sendWriter.flush();
			
			while(true) {
				sendString = tmpbuf.readLine();
				if(sendString == "exit") {
					break;
				}
				sendWriter.println(sendString);
				sendWriter.flush();
			}
			
			sendWriter.close();
			tmpbuf.close();
			m_socket.close();
			
		}catch(IOException e) {
			e.printStackTrace();
		}
	}

	public void setSocket(Socket _socket) {
		m_socket = _socket;
	}
	

}

 

 

[Java 강의93] 자바 Socket 통신으로 채팅 프로그램 만들기2 : 네이버 블로그 (naver.com)

 

[Java 강의93] 자바 Socket 통신으로 채팅 프로그램 만들기2

안녕하세요 모프 입니다. 전 강의에서는 서버와 클라이언트간의 채팅을 다루었습니다만 사실 채팅은 클라이...

blog.naver.com

 

 

 

오늘도 화이팅~