개인 채 팅 과 단체 채 팅 기능 을 실현 한 메 신 저.

앞의 블 로그 (간단 한 C / S 채 팅 방) 에서 우 리 는 이미 다 중 스 레 드 를 사용 하 는 방법 을 언급 했다.서버 의 메 인 스 레 드 는 끊 임 없 는 검색 포트 를 책임 지고, 서브 스 레 드 는 메 시 지 를 수신 하고 발송 하 는 것 을 책임 집 니 다.클 라 이언 트 메 인 스 레 드 는 키보드 메 시 지 를 받 고 서버 에 보 내야 합 니 다. 하위 스 레 드 는 서버 에서 보 낸 메 시 지 를 받 아야 합 니 다.이 간단 한 C / S 대화방 의 실현 에서 단체 채 팅 의 기능 만 실 현 했 을 뿐 개인 채 팅 은 이 루어 지지 않 았 다.그렇다면 본 고 는 개인 채 팅 과 단체 채 팅 을 실현 하 는 것 을 말한다.
우선 우리 가 생각 한 것 은 소식 이 왔 다 는 것 이다. 내 가 어떻게 공적 인 소식 인지, 아니면 사적인 소식 인지 알 겠 는가?그래서 여기 서 정 보 를 처리 해 야 합 니 다. 예 를 들 어 메시지 전후 에 특수 한 문 자 를 추가 하고 우 리 는 협의 문자 라 고 부 릅 니 다.이 를 위해, 우 리 는 프로 토 콜 문 자 를 정의 하기 위해 인 터 페 이 스 를 정의 할 수 있다.
두 번 째 문 제 는 개인 적 인 대화 정보 라면 클 라 이언 트 가 목적 사용자 (개인 적 인 대화 대상) 를 서버 에 보 내 는 것 이다. 그러면 서버 측은 어떻게 그 목적 의 사용 자 를 찾 을 수 있 을 까?여기 서 분명 한 것 은 사용자 와 Socket 의 매 핑 관 계 를 구축 해 야 하기 때문에 우 리 는 map 를 사 용 했 습 니 다. 그러나 이곳 의 map 는 개선 이 필요 합 니 다. 사실 우 리 는 key 가 중복 되 지 않 을 뿐만 아니 라 value 도 중복 되 지 않 습 니 다. 우 리 는 value 를 통 해 key 를 찾 을 수 있 기 때문에 개선 을 했 습 니 다.
그리고 본 실현 에 대해 지적 해 야 할 것 은 서버 서브 스 레 드 가 메 시 지 를 수신 하고 보 내 는 것 입 니 다. 이 안에 클 라 이언 트 가 처음으로 연결 을 만 들 었 을 때 사용자 이름 이 중복 되 는 지 판단 해 야 합 니 다. 즉, key 가 중복 되 지 않도록 해 야 합 니 다. 이에 대응 하려 면 클 라 이언 트 가 처음으로 연결 을 만 들 었 을 때 끊 임 없 는 시 도 를 해 야 합 니 다.제 공 된 이름 이 중복 되 지 않 을 때 까지
코드 는 다음 과 같 습 니 다:
public interface CrazyitProtocol {
	public static final int PROTOCOL_LEN=2; //       public static final,       
	
	public static final String MSG_ROUND="△▽";
	public static final String USR_ROUND="□☆";
	public static final String LOGIN_SUCCESS="☆▷";
	public static final String NAME_REP="-1";
	public static final String PRAVITE_ROUND="◆★";
	public static final String SPLIT_SIGN="☀";

}
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;


public class CrazyitMap extends HashMap {

	//   value      
	public void removeByValue(Object value)
	{
		for(Object key :keySet())
		{
			if(get(key)==value||get(key).equals(value))
			{
				remove(key);
				break;
			}
		}
	}
	
	//   value  
	public Set valueSet()
	{
		Set result=new HashSet();
		for(Object key : keySet())
		{
			result.add(get(key));
		}
		return result;
	}
	
	//   HashMap put  ,      value  
	public V put(K key,V value)
	{
		for(V val : valueSet())
		{
			if(val==value||val.equals(value))
			{
				throw new RuntimeException("MyMap         value");
			}
		}
		return super.put(key, value);	
	}
	
	//   value  key
	public K getKeyByValue(Object value)
	{
		for(K key : keySet())
		{
			if(get(key)==value||get(key).equals(value))
			{
				return key;
			}
		}
		return null;
	}
}
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;


public class Server {
	
	private static final int PORT=30000;
	public static CrazyitMap clients=new CrazyitMap<>();
	
	void init()
	{
		try (
			ServerSocket ss=new ServerSocket(PORT);
		)
		{
			while(true)
			{
				Socket s=ss.accept();
				new Thread(new ServerThread(s)).start();
			}
			
		}catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("       ,       ?");
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Server s=new Server();
		s.init();

	}

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


public class ServerThread implements Runnable {
	
	private Socket s;
	private BufferedReader br=null;
	private PrintStream ps=null;
	
	public ServerThread(Socket s)
	{
		this.s=s;
		
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		try {
			br=new BufferedReader(new InputStreamReader(s.getInputStream()));
			ps=new PrintStream(s.getOutputStream());
			String content=null;
			while((content=br.readLine())!=null)
			{
				if(content.startsWith(CrazyitProtocol.USR_ROUND) //         
						&&content.startsWith(CrazyitProtocol.USR_ROUND))
				{
					String userName=getRealMsg(content);
					if(Server.clients.containsKey(userName)) //     
					{
						System.out.println("  ");
						ps.println(CrazyitProtocol.NAME_REP);
						
					}
					else //      
					{
						System.out.println("  ");
						Server.clients.put(userName, ps);
						ps.println(CrazyitProtocol.LOGIN_SUCCESS);
					}
				}
				else if(content.startsWith(CrazyitProtocol.PRAVITE_ROUND)
						&&content.startsWith(CrazyitProtocol.PRAVITE_ROUND))//           ,      
				{
					String userAndMsg=getRealMsg(content);
					String userName=userAndMsg.split(CrazyitProtocol.SPLIT_SIGN)[0];
					String Msg=userAndMsg.split(CrazyitProtocol.SPLIT_SIGN)[1];
					//           
					Server.clients.get(userName).println(Server.clients.getKeyByValue(ps)
							+"      "+Msg);
					
				}
				else //     
				{
					String Msg=getRealMsg(content);
					for(PrintStream ps : Server.clients.valueSet())
					{
						ps.println(Server.clients.getKeyByValue(this.ps)
								+" :"+Msg);
					}
				}
			}
		} 
		//     ,   Socket           ,
		//               Map   
		catch (IOException e) {
			// TODO Auto-generated catch block
			Server.clients.removeByValue(ps);
			try{
				if(br!=null)
				{
					br.close();
				}
				if(ps!=null)
				{
					ps.close();
				}
				if(s!=null)
				{
					s.close();
				}
			}
			catch(IOException ex)
			{
				ex.printStackTrace();
			}
		}

	}
	//                ,       
	private String getRealMsg(String content) {
		// TODO Auto-generated method stub
		
		return content.substring(CrazyitProtocol.PROTOCOL_LEN, 
				content.length()-CrazyitProtocol.PROTOCOL_LEN);
	}

}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JOptionPane;


public class Client {
	
	private static final int PORT=30000;
	private Socket s=null;
	private PrintStream ps=null;
	private BufferedReader brServer=null; //          
	private BufferedReader keyIn=null; //       
	public void init()
	{
		try
		{
		s=new Socket("127.0.0.1",PORT);
		ps=new PrintStream(s.getOutputStream());
		keyIn=new BufferedReader(new InputStreamReader(System.in));
		brServer=new BufferedReader(new InputStreamReader(s.getInputStream()));
		
		//          ,         
		String tip="";
		while(true)
		{
			String userName=JOptionPane.showInputDialog(tip
					+"     ");
			
			//                      
			ps.println(CrazyitProtocol.USR_ROUND+userName
					+CrazyitProtocol.USR_ROUND);
			String result=brServer.readLine();
			if(result.equals(CrazyitProtocol.NAME_REP))
			{
				tip="     ,   ";
				continue;
			}
			//     
			if(result.equals(CrazyitProtocol.LOGIN_SUCCESS))
			{
				break;
			}
		}
		}
		catch(UnknownHostException ex)
		{
			System.out.println("        ,         !");
			closeRs();
			System.exit(1);
		}
		catch(IOException ex)
		{
			System.out.println("    !     !");
			closeRs();
			System.exit(1);
		}
		
		new Thread(new ClientThread(brServer)); //                  
		
	}
	

	private void closeRs() {
		// TODO Auto-generated method stub
		try{
		if(keyIn!=null)
		{
			keyIn.close();
		}
		if(brServer!=null)
		{
			brServer.close();
		}
		
		if(ps!=null)
		{
			ps.close();
		}
		
		if(s!=null)
		{
			s.close();
		}
		}
		catch(IOException e)
		{
			e.printStackTrace();
		}
		
	}
	
	//             
	public void readAndSend()
	{
		String content=null;
		try
		{
		while((content=keyIn.readLine())!=null)
		{
			//       /  ,  :         
			if(content.startsWith("/")&&content.indexOf(":")>0) 
			{
				content=content.substring(1); //          /
				content=CrazyitProtocol.PRAVITE_ROUND+content.split(":")[0]+CrazyitProtocol.SPLIT_SIGN
						+content.split(":")[1]+CrazyitProtocol.PRAVITE_ROUND;
				ps.println(content);
				
			}
			else //     
			{
				content=CrazyitProtocol.MSG_ROUND+content+CrazyitProtocol.MSG_ROUND;
				ps.println(content);
			}
		}
			
		}
		catch(IOException e)
		{
			System.out.println("      !     !");
			closeRs();
			System.exit(1);
		}
	}
	


	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Client client=new Client();
		client.init();
		client.readAndSend();

	}

}
import java.io.BufferedReader;
import java.io.IOException;


public class ClientThread implements Runnable {
	
	private BufferedReader brServer=null;
	public ClientThread(BufferedReader brServer)
	{
		this.brServer=brServer;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		String content=null;
		
		try
		{
		while((content=brServer.readLine())!=null)
		{
			System.out.println(content);
		}
		}
		catch(IOException e)
		{
			e.printStackTrace();
		}
		finally
		{
			try{
			if(brServer!=null)
			{
				brServer.close();
			}
			}
			catch(IOException e)
			{
				e.printStackTrace();
			}
		}

	}

}

참고 자료: JAVA 광란 강의

좋은 웹페이지 즐겨찾기