소켓통신 - 토이프로젝트

지환·2023년 10월 25일
0

JAVA

목록 보기
38/39
post-thumbnail

소켓통신 - 토이프로젝트 소스코드 공유

package com.database;

DBConnection

package com.database;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class DBConnection {
	public static Connection getConnection() {
		Connection conn=null;
		String url="jdbc:oracle:thin:@127.0.0.1:1521:orcl11";
		String id="scott";
		String pw="tiger";
		String driver="oracle.jdbc.driver.OracleDriver";
		try {
			Class.forName(driver);
			conn=DriverManager.getConnection(url, id, pw);
			System.out.println("DB연결 완료");
		}catch(Exception e) {
			e.printStackTrace();
			System.out.println("DB연결 실패");
		}
		return conn;
	}
	public static void close(Connection c, PreparedStatement p, 
			ResultSet r) {
		try {
			if(r!=null)r.close();
			if(p!=null)p.close();
			if(c!=null)c.close();
		}catch(Exception e) {}
	}
	public static void close(Connection c, PreparedStatement p) {
		try {
			if(p!=null)p.close();
			if(c!=null)c.close();
		}catch(Exception e) {}
	}

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

MemberDao.java

package com.database;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Vector;


public class MemberDao {
	private MemberDao() {}
	private static MemberDao instance=new MemberDao();
	public static MemberDao getInstance() {
		return instance;
	}
	
	private Connection conn; //DB 연결 객체
	private PreparedStatement pstmt; //Query 작성 객체
	private ResultSet rs; //Query 결과 커서
	
	
	//성공 1, 실패 -1, 없음 0
	public int findByUsernameAndPassword(String username, String password) {
		//1. DB 연결
		conn = DBConnection.getConnection();
		
		try {
			//2. Query 작성
			pstmt = conn.prepareStatement("select * from member where username = ? and password = ?");
			
			//3. Query ? 완성 (index 1번 부터 시작)
			//setString, setInt, setDouble, setTimeStamp 등이 있음.
			pstmt.setString(1, username);
			pstmt.setString(2, password);
			
			//4. Query 실행
			//(1) executeQuery() = select = ResultSet 리턴
			//(2) executeUpdate() = insert, update, delete = 리턴 없음.
			rs = pstmt.executeQuery();
			
			//5. rs는 query한 결과의 첫번째 행(레코드) 직전에 대기중
			//결과가 count(*) 그룹함수이기 때문에 1개의 행이 리턴됨. while문이 필요 없음.
			if(rs.next()) { //next()함수는 커서를 한칸 내리면서 해당 행에 데이터가 있으면 true, 없으면 false 반환
				//결과가 있다는 것은 해당 아이디와 비번에 매칭되는 값이 있다는 뜻.
				return 1; //로그인 성공
			}		
		} catch (SQLException e) {
			e.printStackTrace();
		} 
		
		return -1; //로그인 실패
	}
	
	//성공 1, 실패 -1, 
	public int save(MemberDTO member) {
		conn = DBConnection.getConnection();
		
		try {
			pstmt = conn.prepareStatement("insert into member values(?,?,?)");
			pstmt.setString(1, member.getUsername());
			pstmt.setString(2, member.getPassword());
			pstmt.setString(3, member.getNickname());

			pstmt.executeUpdate(); //return값은 처리된 레코드의 개수
			return 1;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return -1;
	}
	
	//성공 Vector<Member>, 실패 null
	public Vector<MemberDTO> findByAll(){
		conn = DBConnection.getConnection();
		Vector<MemberDTO> members = new Vector<>();
		try {
			pstmt = conn.prepareStatement("select * from member");
			rs = pstmt.executeQuery();
			while(rs.next()) {
				MemberDTO member = new MemberDTO();
				member.setUsername(rs.getString("username"));
				member.setPassword(rs.getString("password"));
				member.setNickname(rs.getString("nickname"));

				members.add(member);
			}
			return members;
	
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}
	
	public Vector<String> findNickName() {
	    conn = DBConnection.getConnection();
	    Vector<String> nicknames = new Vector<>();
	    
	    try {
	        pstmt = conn.prepareStatement("select nickname from member");
	        rs = pstmt.executeQuery();
	        while (rs.next()) {
	            String nickname = rs.getString("nickname");
	            nicknames.add(nickname);
	        }
	        return nicknames;
	    } catch (Exception e) {
	        e.printStackTrace();
	    }
	    return null;
	}
	
	public String findNicknameByUsernameAndPassword(String username, String password) {
	    conn = DBConnection.getConnection();
	    
	    try {
	        pstmt = conn.prepareStatement("select nickname from member where username = ? and password = ?");
	        pstmt.setString(1, username);
	        pstmt.setString(2, password);
	        rs = pstmt.executeQuery();
	        /**
	         *  메소드는 현재 레코드의 다음 레코드로 이동하고, 다음 레코드가 있으면 true를 반환하고,
	         *  레코드가 없으면 false를 반환
	         */
	        if (rs.next()) {
	            return rs.getString("nickname");
	        }
	    } catch (Exception e) {
	        e.printStackTrace();
	    }
	    
	    return null;
	}
	
	
	public int deleteMemberByNickname(String nicknameToDelete) {
	    conn = DBConnection.getConnection();

	    try {
	        pstmt = conn.prepareStatement("DELETE FROM member WHERE nickname = ?");
	        pstmt.setString(1, nicknameToDelete);

	        int rowCount = pstmt.executeUpdate();

	        return rowCount; // 삭제된 레코드 수 반환

	    } catch (Exception e) {
	        e.printStackTrace();
	    } finally {
	    }

	    return -1; // 삭제 실패
	}
	
}

MemberDTO.java

package com.database;

import java.io.Serializable;

public class MemberDTO implements Serializable{
	private static final int MINMUM_INPUT = 1;
	private String username;
	private String password;
	private String nickname;
	
	public MemberDTO()
	{
		
	}
	public MemberDTO(String username, String password,String nickname)
	{
		this.username = username;
		this.password = password;
		this.nickname = nickname;
	}
	
	public String getNickname() {
		return nickname;
	}
	public void setNickname(String nickname) {
		this.nickname = nickname;
	}
	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		System.out.println("setUsername 오류");

			this.username = username;

	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {

			this.password = password;

	}
	
	

}

package com.database.zipcodeview

DBConnectionMgr.java

package com.database.zipcodeview;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class DBConnectionMgr {
	static DBConnectionMgr  dbMgr = null;
	/*
	 * null로 초기화 하는 이유는 nullcheck를 해서 null일 때만 새로 인스턴스화 하고 null이 아닐 떄는 계속 사용한다.
	 * 
	 */
	Connection con = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	public static final String _DRIVER = "oracle.jdbc.driver.OracleDriver";
	public static final String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl11";
	public static final String user = "scott";
	public static final String pw = "tiger";
//	
//	String url="jdbc:oracle:thin:@172.30.1.66:1522:orcl11";
//	String id="scott";
//	String pw="tiger";
//	String driver="oracle.jdbc.driver.OracleDriver";
	public static DBConnectionMgr getInstance()
	{
		
		if(dbMgr == null)
		{
			dbMgr =  new DBConnectionMgr();
		}
		return dbMgr;
		
	}
	 // 리턴 타입으로 연결통로를 확보한 con을 얻는다.
	// connection(url,계정정보가 일치해야함) - PrepareStatement(쿼리문 전달, 처리 요청한다.) - ResultSet(커서를 조작하는 메소드) 를 제공 받는다.
	// 앞에 객체가 주입되지 않으면 나머지 뒤에는 모두 null인 상태에 놓인다.
	
	public Connection getConnection()
	{
		/*
		 * 예외처리 시 try..catch 블록을 사용하는데 멀티 블록이 가능함. 단 하위에서 상위클래스로 처리함.
		 * 
		 * 중복으로 예외처리를 하면 되는데 범위를 따져야한다. -> 적은 범위를 처음으로 했으면 다음엔 더 넓은 범위 
		 * 그 다음은 더 넓은 범위로 해야한다.
		 */
	
		try {
			
			// 각 제조사의 드라이버 클래스를 로딩하기
			/*
			 * 물리적으로 떨어져있는 오라클 서버와 연결통로 확보 // ClassNotFoundException
			 * getConnection 메소드의 원형도 Static 붙어 있다. + 하나다 복제 허용 안함 - 하나로 사용하고 반납하고 사용한다.
			 * getConnection 메소드 호출 때문에 예외처리를 하였다. 
			 * 이유는 URL이 존재하지 않을 경우 - 런타임오류(실행에러) + 논리의 오류 + 사이드 이팩트
			 * 신뢰도가 높은 코드는 + 지역변수를 이용해야한다.
			 */
			Class.forName("oracle.jdbc.driver.OracleDriver");
			// 물리적으로 떨어져 있는 오라클 서버와 연결통로 확보 
			con = DriverManager.getConnection(url,user,pw);
		}catch(ClassNotFoundException e)
		{
			System.out.println("ojdbc6.jar를 설정하지 않았다. 그래서 클래스를 못 찾는다.");
		
		}
		
		catch (Exception e) { // 비번이 맞지 않을 때
			e.printStackTrace();
		}
		return con;
	}
	
	/*
	 * 29 && 31번 호출 시 에러가 없다면 catch 블록은 실행하지 않는다.
	 */
	public static void freeConnection(ResultSet rs, PreparedStatement pstmt, Connection con){
		try {
			if(rs !=null) rs.close();
			if(pstmt !=null) pstmt.close();
			if(con !=null) con.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void freeConnection(PreparedStatement pstmt, Connection con){
		try {
			if(pstmt !=null) pstmt.close();
			if(con !=null) con.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void freeConnection(ResultSet rs, CallableStatement cstmt, Connection con){
		try {
			if(rs !=null) rs.close();
			if(cstmt !=null) cstmt.close();
			if(con !=null) con.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void freeConnection(CallableStatement cstmt, Connection con){
		try {
			if(cstmt !=null) cstmt.close();
			if(con !=null) con.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

package com.ui;

LoginForm.java

package com.ui;

import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import com.database.MemberDTO;
import com.database.MemberDao;
import com.soket.client.SocketClient;


public class LoginForm extends JFrame implements ActionListener {
	/////////////////////////////////////////////////////
	/* 선언부 */
	/////////////////////////////////////////////////////
	String imgPath="C:\\Users\\GDJ\\Desktop\\ChatJava\\ChattingProgram\\src\\image\\";
	// 
	//D:\WorkSpace_Java\Java\dev_java\\src\image\\;
	JLabel jlb_id = new JLabel("아이디");
	JLabel jlb_pw = new JLabel("패스워드");

	Font jl_font = new Font("휴먼매직체", Font.BOLD, 17);
	JTextField jtf_id = new JTextField("");
	JPasswordField jpf_pw = new JPasswordField("");

	JButton jbtn_login = new JButton(
			new ImageIcon(imgPath+"login.png"));
	JButton jbtn_join = new JButton(
			new ImageIcon(imgPath+"confirm.png"));
	

	// JPanel에 쓰일 이미지아이콘
	ImageIcon ig = new ImageIcon(imgPath+"main.png");
	MemberShipView mbv = new MemberShipView(this);
	

	/////////////////////////////////////////////////////
	/* 생성자 */
	/////////////////////////////////////////////////////
	public LoginForm(){
		initDisplay();
	}

	/////////////////////////////////////////////////////
	/* jpanal 오버라이드 */
	/////////////////////////////////////////////////////

	/* 배경이미지 */
	class mypanal extends JPanel {
		public void paintComponent(Graphics g) {
			g.drawImage(ig.getImage(), 0, 0, null);
			setOpaque(false);
			super.paintComponents(g);
		}
	}

	/////////////////////////////////////////////////////
	/* 화면처리 */
	/////////////////////////////////////////////////////
	public void initDisplay() {
		setContentPane(new mypanal());
		
		/* 버튼과 텍스트필드 구성 */
		jbtn_join.addActionListener(this);
		jbtn_login.addActionListener(this);
		this.setLayout(null);
		this.setTitle("자바채팅 ver.1");
		this.setSize(350, 600);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setVisible(true);
		this.setLocation(800, 250);
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		// id 라인
		jlb_id.setBounds(45, 200, 80, 40);
		jlb_id.setFont(jl_font);
		jtf_id.setBounds(110, 200, 185, 40);
		this.add(jlb_id);
		this.add(jtf_id);

		// pw 라인
		jlb_pw.setBounds(45, 240, 80, 40);
		jlb_pw.setFont(jl_font);
		jpf_pw.setBounds(110, 240, 185, 40);
		this.add(jlb_pw);
		this.add(jpf_pw);

		// 로그인 버튼 라인
		jbtn_login.setBounds(175, 285, 120, 40);
		this.add(jbtn_login);

		// 회원가입 버튼 라인
		jbtn_join.setBounds(45, 285, 120, 40);
		this.add(jbtn_join);		
	}

	public static void main(String[] args) throws Exception {
		new LoginForm();
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		Object obj = e.getSource();
		String username = jtf_id.getText();
		String password = jpf_pw.getText();
		MemberDTO member = new MemberDTO();
		MemberDao dao = MemberDao.getInstance();
		int rs = dao.findByUsernameAndPassword(username, password);


		/*
		 * rs에서 에러가 계속적으로 발생함 "PASSWORD": 부적합한 식별자 -> 에러 해결
		 */
		if (obj == jbtn_join) {

			mbv.initDisplay();

		} 
		else if (obj == jbtn_login) {
			if (rs == 1){
				JOptionPane.showMessageDialog(null, "로그인 성공");
				String nickName = dao.findNicknameByUsernameAndPassword(username, password);
				SocketClient sc = new SocketClient(nickName);
				sc.initDisplay();
				sc.init();
				dispose();

			}
			else
			{
				try{JOptionPane.showMessageDialog(null, "로그인 실패");}
				catch (Exception e1) {e1.printStackTrace(); }
					// TODO: handle exception
				}
				


			}

				}
			
		}

java

package com.ui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;

import com.database.MemberDTO;
import com.database.MemberDao;
import com.soket.client.SocketClient;


public class MemberListFrame extends JFrame implements ActionListener{

	MemberShipView memberShipView = null;
	private JPanel contentPane;
	private JTable table;
	String username;

	JButton jbtn_select	  = new JButton("조회");
	JButton jbtn_correction = new JButton("수정");
	JButton jbtn_del = new JButton("삭제");
	
	private JLabel lbTitle;
	private JButton logoutBtn;
	private DefaultTableModel tableModel;
	/**
	 * Launch the application.
	 */
	

	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					MemberListFrame frame = new MemberListFrame();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * 이 쪽이 문제다. String username이 나왔는데, 이 부분이 nullPointException이 나오는 부분이다.
	 * @param memberShipView 
	 */
	public MemberListFrame() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(1032, 584);
		setLocationRelativeTo(null);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		contentPane.setLayout(new BorderLayout(0, 0));
		setContentPane(contentPane);
		
		lbTitle = new JLabel("회원정보");
		lbTitle.setHorizontalAlignment(SwingConstants.CENTER);
		lbTitle.setFont(new Font("나눔고딕", Font.BOLD, 20));
		lbTitle.setPreferredSize(new Dimension( 738, 50 ));
		contentPane.add(lbTitle, BorderLayout.NORTH);
		
		//샘플 데이터 가져오기 (나중에 DB에서 가져와야 함)
		Vector<String> memberName = Sample.getmemberheader();
		MemberDao dao = MemberDao.getInstance();
		Vector<MemberDTO> members = dao.findByAll();
		
		//tableModel에 열 이름과 행 개수 설정
		tableModel = new DefaultTableModel(memberName,0);
		
		//tableModel에 전체 행 넣기
		for (int i = 0; i < members.size(); i++) {
			Vector<Object> row = new Vector<>();
			row.addElement(members.get(i).getUsername());
			row.addElement(members.get(i).getPassword());
			row.addElement(members.get(i).getNickname());
			tableModel.addRow(row);
		}
		
		jbtn_select.addActionListener(this);
		jbtn_correction.addActionListener(this);
		jbtn_del.addActionListener(this);
		//tableModel을 JTable에 넣기
		table = new JTable(tableModel);
		table.setFont(new Font("돋움", Font.PLAIN, 20));
		table.setRowHeight(25);
		
		//JTable에 scroll달아서 add하기
		JScrollPane scrollPane = new JScrollPane(table);
		contentPane.add(scrollPane, BorderLayout.CENTER);
		
		logoutBtn = new JButton("나가기");
		contentPane.add(logoutBtn, BorderLayout.SOUTH);
		logoutBtn.addActionListener(this);
		setVisible(true);
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		Object obj = e.getSource();
		if(obj == logoutBtn)
		{
			JOptionPane.showMessageDialog(null, "채팅창으로 돌아갑니다.");
			
			dispose();
			
		}
		

		else
		{
			setVisible(true);	
		}
		


		
	}

}

MemberShipView.java

package com.ui;
import java.awt.FlowLayout;
import javax.swing.JPasswordField;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

import com.database.MemberDTO;
import com.database.MemberDao;
import com.soket.client.SocketClient;




public class MemberShipView extends JDialog implements ActionListener{
    //선언부
    JPanel jp_center = new JPanel();
    JLabel jlb_id = new JLabel("아이디");
    JTextField jtf_id = new JTextField(10);
    
    JLabel jlb_pw = new JLabel("패스워드");
    JTextField jtf_pw = new JTextField(10);
    
    JLabel jlb_nickName = new JLabel("닉네임");
    JTextField jtf_nickName = new JTextField(20);


	JLabel jlb_name = new JLabel("성명");
    JTextField jtf_name = new JTextField(30);
    JLabel jlb_gender = new JLabel("성별");
    String[] genderList = {"남자","여자"};
    JComboBox jcb_gender = new JComboBox(genderList);
    JLabel 		jlb_zipcode = new JLabel("우편번호");
    public JTextField 	jtf_zipcode = new JTextField(6);
    JLabel 		jlb_address = new JLabel("주소");
    public JTextField 	jtf_address = new JTextField(100);
    JButton     jbtn_zipcode = new JButton("우편번호찾기");
    JScrollPane jsp = null;
    JPanel jp_south = new JPanel();
    JButton jbtn_ins = new JButton("등록");
    JButton jbtn_close = new JButton("닫기");
    ZipCodeView zv = new ZipCodeView(this);
    JPasswordField jpf_pw = new JPasswordField(10);
    String nickName = null;
    LoginForm lf = null;
    //생성자

    public MemberShipView(LoginForm loginForm){
    	this.lf = loginForm;
    }
    
    //화면처리부
    public void initDisplay() {
    	jbtn_close.addActionListener(this);
    	jbtn_ins.addActionListener(this);
        jbtn_zipcode.addActionListener(this);
        jp_center.setLayout(null);
        jlb_id.setBounds(20, 20, 100, 20);
        jtf_id.setBounds(120, 20, 120, 20);
        jtf_pw.setBounds(120, 45, 120, 20);
        
        jpf_pw.setEchoChar('*');
        jpf_pw.setBounds(120, 45, 120, 20);
        jp_center.add(jpf_pw);
        jlb_nickName.setBounds(20, 70, 100, 20);
        jtf_nickName.setBounds(120, 70, 150, 20);
        jlb_name.setBounds(20, 95, 100, 20);
        jtf_name.setBounds(120, 95, 150, 20);
        jlb_gender.setBounds(20, 120, 100, 20);
        jcb_gender.setBounds(120, 120, 150, 20);
        jcb_gender.setFont(new Font("굴림",1,14));
        jlb_zipcode.setBounds(20, 145, 100, 20);
        jtf_zipcode.setBounds(120, 145, 100, 20);
        jbtn_zipcode.setBounds(230, 145, 120, 20);
        jlb_address.setBounds(20, 170, 100, 20);
        jtf_address.setBounds(120, 170, 250, 20);
        jp_center.add(jlb_id);
        jp_center.add(jtf_id);
        jp_center.add(jlb_pw);
        jp_center.add(jtf_pw);
        jp_center.add(jlb_nickName);
        jp_center.add(jtf_nickName);
        jp_center.add(jlb_name);
        jp_center.add(jtf_name);
        jp_center.add(jlb_gender);
        jp_center.add(jcb_gender);
        jp_center.add(jlb_zipcode);
        jp_center.add(jtf_zipcode);
        jp_center.add(jbtn_zipcode);
        jp_center.add(jlb_address);
        jp_center.add(jtf_address);
        jp_south.setLayout(new FlowLayout(FlowLayout.RIGHT));
        jp_south.add(jbtn_ins);
        jp_south.add(jbtn_close);
        this.add("South",jp_south);
        jsp = new JScrollPane(jp_center);
        this.add("Center",jsp);
        this.setTitle("회원가입");
        this.setSize(400, 500);
        this.setVisible(true);
    }
    public static void main(String[] args) {
    	MemberShipView ms = new MemberShipView();
        ms.initDisplay();
    }
    
    public MemberShipView()
    {
    	
    }
    

//    public MemberShipView()
//    {
//        jbtn_ins.addActionListener(new ActionListener() {
//			
//			@Override
//			public void actionPerformed(ActionEvent e) {
//				Object obj = e.getSource();
//				MemberDTO member = new MemberDTO();
//				member.setId(jtf_id.getText());
//				member.setPw(jtf_pw.getText());
//				member.setNickName(jtf_nickName.getText());
//				member.setGender(jlb_gender.getText());
//				member.setZipcode(jtf_zipcode.getText());
//				member.setAddress(jtf_address.getText());
//				
//				MemberDao dao = MemberDao.getInstance();
//				int result = dao.save(member);
//			
//				if(result == 1) {
//					JOptionPane.showMessageDialog(null, "회원가입이 완료되었습니다.");
//					dispose();
//				}else {
//					JOptionPane.showMessageDialog(null, "회원가입이 실패하였습니다.");
//					dispose();
//				}	
//			}
//		});
//
//	}
    
//    @Override
//	public void actionPerformed(ActionEvent e) {
//    	
//		Object obj = e.getSource();
//		MemberDTO member = new MemberDTO();
//		member.setId(jtf_id.getText());
//		member.setPw(jtf_pw.getText());
//		member.setNickName(jtf_nickName.getText());
//		String selectedGender = (String) jcb_gender.getSelectedItem();
//		member.setGender(selectedGender);
//		member.setZipcode(jtf_zipcode.getText());
//		member.setAddress(jtf_address.getText());
//		
//		
//    	if(obj == jbtn_zipcode) 
//    	{
//    		zv.initDisplay();
//    	}
////    	else if(result == 1) {
////			JOptionPane.showMessageDialog(null, "회원가입이 완료되었습니다.");
////			dispose();
////		}else if(result == -1) {
////			JOptionPane.showMessageDialog(null, "회원가입이 실패하였습니다.");
////			dispose();
////
////			
////	}
////		else
////		{
////			
////		}
////    
////	
////}}


    
   
    	
    @Override
    public void actionPerformed(ActionEvent e) {
    	System.out.println("action");
        Object obj = e.getSource();
//        MemberDTO member = new MemberDTO();
//        member.setUsername(jtf_id.getText());
//        member.setPassword(jpf_pw.getText());
//        member.setNickname(jtf_nickName.getText());
//        MemberDao dao = MemberDao.getInstance();
//        String nickName = jtf_nickName.getText();
//        int rs = dao.save(member);
        
        
        
        if(obj == jbtn_zipcode) {
        	zv.initDisplay();

        }
        else if (obj == jbtn_ins)
        {
        	if(isInputValid())
        	{
        		 MemberDTO member = new MemberDTO();
                 member.setUsername(jtf_id.getText());
                 member.setPassword(jpf_pw.getText());
                 member.setNickname(jtf_nickName.getText());
                 MemberDao dao = MemberDao.getInstance();
                 int rs = dao.save(member);
                 if(rs == 1)
                 {
                	 JOptionPane.showMessageDialog(this, "회원가입이 완료되었습니다.", "INFO", JOptionPane.INFORMATION_MESSAGE);
                     dispose();
                 }
                 else
                 {
                	 JOptionPane.showMessageDialog(this, "회원가입이 실패하였습니다.", "ERROR", JOptionPane.ERROR_MESSAGE);
                 }
        	}
            
        	/*
        	 * 여기는 추후에 디비연동하여 값을 받아와야함
        	 */

        }

        else if(obj == jbtn_close)
        {
        	
        	JOptionPane.showMessageDialog(this,"회원가입이 실패하였습니다.","INFO", JOptionPane.INFORMATION_MESSAGE);
        	dispose();
        }
    }

//사용자 입력이 유효한지 검증

    /**
     * @inInputVaild() : 메소드
     * 1. 회원가입 창에서 모든 필드를 입력 할 수 있도록 하는 메소드 -> 어디서 사용? -> (obj == jbtn_ins) 
     * @return boolean --> if문 내에서 사용하기 위해서 
     */
private boolean isInputValid() {
 if (isEmptyOrNull(jtf_id.getText()) ||
     isEmptyOrNull(jpf_pw.getText()) ||
     isEmptyOrNull(jtf_nickName.getText()) ||
     isEmptyOrNull(jtf_name.getText()) ||
     isEmptyOrNull(jtf_zipcode.getText()) ||
     isEmptyOrNull(jtf_address.getText())) {
     JOptionPane.showMessageDialog(this, "필드를 모두 채워주세요.", "ERROR", JOptionPane.ERROR_MESSAGE);
     return false;
 }
 return true;
}

//문자열이 비어 있는지 또는 null인지 확인
private boolean isEmptyOrNull(String str) {
 return str == null || str.trim().isEmpty();
}}

ZipCodeView.java

package com.ui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;

import com.database.zipcodeview.DBConnectionMgr;

public class ZipCodeView extends JFrame implements ActionListener, FocusListener, MouseListener {
	//선언부
	String zdo = null;
	//물리적으로 떨어져 있는 db서버와 연결통로 만들기
	Connection 			con 	= null;
	//위에서 연결되면 쿼리문을 전달할 전령의 역할을 하는 인터페이스 객체 생성하기
	PreparedStatement 	pstmt 	= null;
	//조회된 결과를 화면에 처리해야 하므로 오라클에 커서를 조작하기 위해 ResultSet추가
	ResultSet 			rs 		= null;
	//JFrame 은 기본적으로 BorderLayout이다(동,서,남,북,중앙 배치)
	//디폴트는 FlowLayout, ->  BorderLayout -> setLayout
	//jp_north.add("Center", jtf_dong)
	//jp_north.add("West",jbtn_search)
	JPanel jp_north = new JPanel();//Div태그 span생각
	//insert here
	String zdos[] = {"전체","서울","경기","강원"};
	String zdos2[] = {"전체","부산","전남","대구"};
	Vector<String> vzdos = new Vector<>();//vzdos.size()==>0
	JComboBox jcb_zdo = new JComboBox(zdos);//West
	JComboBox jcb_zdo2 = null;//West
	JTextField jtf_search = new JTextField("동이름을 입력하세요.");//Center
	JButton jbtn_search = new JButton("조회");//East
	String cols[] = {"우편번호","주소"};
	String data[][] = new String[0][2];
	DefaultTableModel dtm_zipcode = new DefaultTableModel(data,cols);
	JTable jtb_zipcode = new JTable(dtm_zipcode);
	JTableHeader jth = jtb_zipcode.getTableHeader();
	JScrollPane jsp_zipcode = new JScrollPane(jtb_zipcode
			,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED
			,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
	String zdos3[] = null;
	 DBConnectionMgr dbMgr = null;//싱글톤 패턴으로 관리한다. 복제본을 만들지 않는다. 절대로....
	MemberShipView memberShipView = null;//null이 뭔가를 가리키는 시점은 ZipCodeVIew생성자가 호출될때
	//생성자
	public ZipCodeView() {
	}

	public ZipCodeView(MemberShipView memberShipView) {
		this.memberShipView = memberShipView;// 재정의, 치환하기
	}

	//화면처리부
	public void initDisplay() {
		jtb_zipcode.requestFocus();
		jtf_search.addFocusListener(this);
		jtb_zipcode.addMouseListener(this);
		jbtn_search.addActionListener(this);
		jtf_search.addActionListener(this);
		//북쪽 배치하는 속지를 FlowLayout-> 동서남북중앙 - UI솔루션
		jp_north.setLayout(new BorderLayout());
		/*	*/
		//vzdos.copyInto(zdos2);
		for(int x=0;x<zdos2.length;x++) {
			vzdos.add(zdos2[x]);
		}
		for(String s:vzdos) {
			System.out.println("s===>"+s);
		}
		//jcb_zdo2 = new JComboBox(zdos3);//West
		//jp_north.add("East",jcb_zdo2);
		jp_north.add("Center",jtf_search);
		jp_north.add("East",jbtn_search);
		this.add("North",jp_north);
		this.add("Center",jsp_zipcode);
		this.setTitle("우편번호 검색");
		this.setSize(430, 400);
		this.setVisible(true);
	}
	//메인메소드
	public static void main(String[] args) {
		ZipCodeView zcs = new ZipCodeView();
		zcs.initDisplay();//화면이 먼저 열리도록 하고 오라클서버를 나중에 연결하자
		//zcs.refreshData("가산");
	}

	public void refreshData(String dong) {
		List<Map<String,Object>> list = new ArrayList<>();
		StringBuilder sql = new StringBuilder();
		sql.append("SELECT zipcode, address    ");
		sql.append("  FROM zipcode_t           ");
		sql.append(" WHERE dong LIKE ?||'%'");
		dbMgr = DBConnectionMgr.getInstance();
		try {
			con = dbMgr.getConnection();//물리적으로 떨어져 있는 서버와 연결통로 확보
			pstmt = con.prepareStatement(sql.toString());//쿼리문을 먼저 스캔하여 있을 지 모르는 변수의 자리를 치환할것.
			pstmt.setString(1, dong);//dong, 당산, 가산, 공덕
			rs = pstmt.executeQuery();
			Map<String,Object> rmap = null;
			while(rs.next()) {
				rmap = new HashMap<>();
				rmap.put("zipcode", rs.getInt("zipcode"));
				rmap.put("address", rs.getString("address"));
				list.add(rmap);
			}
			System.out.println(list);//주소번지가 33번 출력될것이다. - 단위테스트 하자
			//메소드 설계가 리턴타입이 빠져 있으므로 화면 처리까지 여기서 해야 함.
			for(int i=0;i<list.size();i++) {//33번 반복됨 - row수
				Map<String, Object> map = list.get(i);
				Vector<Object> v = new Vector<>();
				v.add(0,map.get("zipcode"));
				v.add(1,map.get("address"));
				dtm_zipcode.addRow(v);
			}
		} catch (SQLException se) {
			System.out.println(sql.toString());//출력된 쿼리문을 갈무리해서 토드에서 확인해 볼것.
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		Object obj = e.getSource();
		if(obj == jbtn_search || obj == jtf_search) {
			System.out.println(jtf_search.getText());//당산
			String dong = jtf_search.getText();
			refreshData(dong);
		}
		
		
		
	}

	@Override
	public void focusGained(FocusEvent e) {
		Object obj = e.getSource();
		if(obj == jtf_search) {
			jtf_search.setText("");
		}
		
	}

	@Override
	public void focusLost(FocusEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent e) {
		if(e.getClickCount()==2) {//더블클릭한거야?
			int index = jtb_zipcode.getSelectedRow();//1.8부터 오토박싱을 통해서 int와 Wrapper클래스는 자동으로 형전환
			int zipcode = (int)dtm_zipcode.getValueAt(index, 0);//선택된 로우의 우편번호가 담김
			String address = (String)dtm_zipcode.getValueAt(index, 1);
			System.out.println(zipcode +",  "+ address);//

			memberShipView.jtf_zipcode.setText(String.valueOf(zipcode));
			memberShipView.jtf_address.setText(String.valueOf(address));
			dispose();
		}
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
}

package com.soket.server;

SocketServerThread.java

package com.soket.server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.StringTokenizer;


public class SocketServerThread extends Thread {
	public SocketServer ts = null;
	Socket client = null;
	ObjectOutputStream oos = null;
	ObjectInputStream ois = null;
	String chatName = null;//현재 서버에 입장한 클라이언트 스레드 닉네임 저장
	public SocketServerThread(SocketServer ts) {
		this.ts = ts;
		this.client = ts.socket;
		try {
			oos = new ObjectOutputStream(client.getOutputStream());
			ois = new ObjectInputStream(client.getInputStream());
			String msg = (String)ois.readObject();
			ts.jta_log.append(msg+"\n");
			StringTokenizer st = new StringTokenizer(msg,"#");
			st.nextToken();//100
			chatName = st.nextToken();
			ts.jta_log.append(chatName+"님이 입장하였습니다.\n");
			for(SocketServerThread tst:ts.globalList) {
			//이전에 입장해 있는 친구들 정보 받아내기
				//String currentName = tst.chatName;
				this.send(100+"#"+tst.chatName);
			}
			//현재 서버에 입장한 클라이언트 스레드 추가하기
			ts.globalList.add(this);
			this.broadCasting(msg);
		} catch (Exception e) {
			System.out.println(e.toString());
		}
	}
	//현재 입장해 있는 친구들 모두에게 메시지 전송하기 구현
	public void broadCasting(String msg) {
		for(SocketServerThread tst:ts.globalList) {
			tst.send(msg);
		}
	}
	public void LogoutRequest(String nickName) {
	    try {
	        String message = nickName + "님이 퇴장하였습니다.";
	        broadCasting(210 + "#" + nickName + "#" + message);
	        // 사용자 목록 업데이트
	        removeList(nickName);
	    } catch (Exception e) {
	        e.printStackTrace();
	    }
	}

	// 사용자 목록에서 사용자 제거
	public void removeList(String nickName) {
	    for (SocketServerThread tst : ts.globalList) {
	        if (tst != null && tst.chatName.equals(nickName)) {
	            ts.globalList.remove(tst);
	            break;
	        }
	    }
	}

	
	// 사용자 목록을 클라이언트에게 전송
	public void sendUserList(SocketServerThread clientThread) throws IOException {
	    StringBuilder userListMessage = new StringBuilder("100#");
	    for (SocketServerThread t : ts.globalList) {
	        userListMessage.append(t.chatName).append("#");
	    }
	    clientThread.send(userListMessage.toString());
	}
	
	//클라이언트에게 말하기 구현
	public void send(String msg) {
		try {
			oos.writeObject(msg);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public void run() {
		String msg = null;
		boolean isStop = false;
		try {
			//while(true) {//무한루프에 빠질 수 있다.
			run_start:
			while(!isStop) {
				msg = (String)ois.readObject();
				ts.jta_log.append(msg+"\n");
				ts.jta_log.setCaretPosition
				(ts.jta_log.getDocument().getLength());
				StringTokenizer st = null;
				int protocol = 0;//100|200|201|202|500
				if(msg !=null) {
					st = new StringTokenizer(msg,"#");
					protocol = Integer.parseInt(st.nextToken());//100
				}
				switch(protocol) {
					case 200:{
						
					}break;
					case 201:{
						String nickName = st.nextToken();
						String message = st.nextToken();
						broadCasting(201
								   +"#"+nickName
								   +"#"+message);
					}break;
					case 202:{
						String nickName = st.nextToken();
						String afterName = st.nextToken();
						String message = st.nextToken();
						this.chatName = afterName;
						broadCasting(202
								+"#"+nickName
								+"#"+afterName
        						+"#"+message);
					}break;
					
					case 210: // 삭제 소켓통신 actionPerformed와 연동하여 작성 
					{
						String nickName = st.nextToken();
						String message = st.nextToken();
						String del = "회원탈퇴 했습니다.";
						broadCasting(210
								+"#"+nickName + "#" + del);
						oos.writeObject(210 + "#" + nickName + "#"+ del);
						
						
					}break;

					case 500:{
						String nickName = st.nextToken();
						ts.globalList.remove(this);
						broadCasting(500
								+"#"+nickName);
					}break run_start;
				}/////////////end of switch
			}/////////////////end of while			
		} catch (Exception e) {
			// TODO: handle exception
		}
	}/////////////////////////end of run
}
  • 클라이언트 A가 서버에 접속하면 tst.chatName은 클라이언트 A의 대화명이다.

  • 클라이언트 B가 서버에 접속하면 tst.chatName은 클라이언트 B의 대화명이다.

  • 이전에 서버에 이미 접속한 클라이언트들의 대화명을 현재 서버에 접속한 클라이언트(클라이언트 B)에게 보내기 위해 사용한다. 즉, 이전에 서버에 접속한 클라이언트들의 대화명을 클라이언트 B에게 알리는 것이다.

  • 따라서 tst.chatName은 현재 클라이언트 B의 대화명이 아닌, 이미 서버에 접속한 클라이언트들의 대화명을 나타낸다. 이를 통해 클라이언트 B는 서버에 접속한 다른 클라이언트들의 대화명을 알 수 있게 된다.

LogoutRequest: 이 메서드는 클라이언트가 로그아웃을 요청했을 때 호출됩니다. 서버 측에서 클라이언트의 로그아웃을 처리하며, 사용자 목록을 업데이트하고 로그아웃 메시지를 클라이언트에게 전송합니다. 이로써 서버 측의 사용자 목록과 클라이언트 측의 화면(GUI) 양쪽에 로그아웃 상태가 반영됩니다.

removeList: removeList 메서드는 서버 측에서 사용자 목록에서 특정 사용자를 제거합니다. 이 메서드는 LogoutRequest 메서드 내부에서 호출되며, 클라이언트가 로그아웃한 경우 해당 사용자를 사용자 목록에서 제거하여 서버 측의 사용자 목록을 갱신합니다.

sendUserList: sendUserList 메서드는 서버 측에서 사용자 목록을 클라이언트에게 전송합니다. 이 메서드는 사용자가 서버에 처음 접속할 때 또는 사용자 목록을 요청했을 때 사용됩니다. 클라이언트는 이 목록을 받아 사용자 목록을 화면에 표시하거나 업데이트합니다.

따라서 이러한 메서드는 주로 서버 측에서 실행되고, 그 결과가 클라이언트 측의 GUI에 반영됩니다. 사용자 목록, 로그아웃 메시지 및 다른 사

SocketServer.java

package com.soket.server;

import java.awt.Color;
import java.awt.FlowLayout;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Calendar;
import java.util.List;
import java.util.Vector;

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


public class SocketServer extends JFrame implements Runnable{
	SocketServerThread 		tst 		= null;
	List<SocketServerThread> 	globalList 	= null;
	ServerSocket 			server 		= null;
	Socket 					socket 		= null;
	JTextArea 				jta_log = new JTextArea(10,30);
	JScrollPane 			jsp_log = new JScrollPane(jta_log
			                                         ,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED
			                                         ,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
	JPanel 		jp_north = new JPanel();
	public void initDisplay() {
		jp_north.setLayout(new FlowLayout(FlowLayout.LEFT));
		jta_log.setBackground(Color.orange);
		this.add("North",jp_north);
		this.add("Center",jsp_log);
		this.setSize(500, 400);
		this.setVisible(true);
		
	}
	//서버소켓과 클라이언트측 소켓을 연결하기
	@Override
	public void run() {
		//서버에 접속해온 클라이언트 스레드 정보를 관리할 벡터 생성하기 
		globalList = new Vector<>();
		boolean isStop = false;
		try {
			server = new ServerSocket(3002);
			jta_log.append("Server Ready.........\n");
			while(!isStop) {
				socket = server.accept();
				jta_log.append("client info:"+socket+"\n");				
				SocketServerThread tst = new SocketServerThread(this);
				tst.start();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		SocketServer ts = new SocketServer();
		ts.initDisplay();
		Thread th = new Thread(ts);
		th.start();
	}

	public String setTimer() {
		Calendar cal = Calendar.getInstance();
		int yyyy = cal.get(Calendar.YEAR);
		int mm = cal.get(Calendar.MONTH)+1;
		int day =  cal.get(Calendar.DAY_OF_MONTH);
		return yyyy+"-"+
			   (mm < 10 ? "0"+mm:""+mm)+"-"+
			   (day < 10 ? "0"+day:""+day);
	}////////////////end of setTimer
}

Protocol

package com.soket.server;

public class Protocol {
	public final static int LOGIN = 100;
	public final static int MESSAGE = 200;
	public final static int DELETE = 210;
	public final static int LOGOUT = 190;
	public final static int CHANGE = 202;
}

package com.soket.client;

SocketClient

package com.soket.client;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.table.DefaultTableModel;

import com.database.MemberDTO;
import com.database.MemberDao;
import com.soket.server.Protocol;
import com.ui.LoginForm;
import com.ui.MemberListFrame;
import com.ui.MemberShipView;





public class SocketClient extends JFrame implements ActionListener {
	////////////////통신과 관련한 전역변수 추가 시작//////////////
	Socket 				socket 	= null;
	ObjectOutputStream 	oos 	= null;//말 하고 싶을 때
	ObjectInputStream 	ois		= null;//듣기 할 때
	String 				nickName;//닉네임 등록
	String					 contents;

	////////////////통신과 관련한 전역변수 추가  끝  //////////////
	JPanel jp_second	  = new JPanel();
	JPanel jp_second_south = new JPanel();
	JButton jbtn_change	  = new JButton("대화명변경");
	JButton jbtn_list	  = new JButton("회원 리스트");
	JButton jbtn_font	  = new JButton("글자색");
	JButton jbtn_exit	  = new JButton("나가기");
	JButton jbtn_del = new JButton("회원탈퇴");
	String cols[] 		  = {"대화명"};
	String data[][] 	  = new String[0][1];
	DefaultTableModel dtm = new DefaultTableModel(data,cols);
	JTable			  jtb = new JTable(dtm);
	JScrollPane       jsp = new JScrollPane(jtb);
	JPanel jp_first 		= new JPanel();
	JPanel jp_first_south 	= new JPanel();
	JTextField jtf_msg = new JTextField(20);//south속지 center
	JButton jbtn_send  = new JButton("전송");//south속지 east
	JTextArea jta_display = null;
	JScrollPane jsp_display = null;
	MemberListFrame mbl = null;
	
	public SocketClient() {

	}
	
	

	public SocketClient(String nickName2) {
		this.nickName = nickName2;
	}




	public void initDisplay() {
		

		jbtn_list.addActionListener(this);
		jbtn_del.addActionListener(this);
		jbtn_send.addActionListener(this);
		jtf_msg.addActionListener(this);
		jbtn_exit.addActionListener(this);
		jbtn_change.addActionListener(this);
		jbtn_font.addActionListener(this);
		this.setLayout(new GridLayout(1,2));
		jp_second.setLayout(new BorderLayout());
		jp_second.add("Center",jsp);
		jp_second_south.setLayout(new GridLayout(2,2));
		jp_second_south.add(jbtn_change);
		jp_second_south.add(jbtn_del);
		jp_second_south.add(jbtn_del);
		jp_second_south.add(jbtn_list);
		jp_second_south.add(jbtn_exit);
		jp_second.add("South",jp_second_south);
		jp_first.setLayout(new BorderLayout());
		jp_first_south.setLayout(new BorderLayout());
		jp_first_south.add("Center",jtf_msg);
		jp_first_south.add("East",jbtn_send);
		jta_display = new JTextArea();
		jta_display.setLineWrap(true);
		jta_display.setOpaque(false);
		Font font = new Font("굴림체",Font.BOLD,16);
		jta_display.setFont(font);
		jsp_display = new JScrollPane(jta_display);		
		jp_first.add("Center",jsp_display);
		jp_first.add("South",jp_first_south);
		this.add(jp_first);
		this.add(jp_second);
		this.setTitle(nickName);
		this.setSize(800, 550);
		this.setVisible(true);
	}
	public static void main(String args[]) {
		JFrame.setDefaultLookAndFeelDecorated(true);
		SocketClient sc = new SocketClient();
		sc.initDisplay();
		sc.init();
	}

	public void init() {
		try {
			//서버측의 ip주소 작성하기
			socket = new Socket("172.16.2.7",3002);
			oos = new ObjectOutputStream(socket.getOutputStream());
			ois = new ObjectInputStream(socket.getInputStream());
			//initDisplay에서 닉네임이 결정된 후 init메소드가 호출되므로
			//서버에게 내가 입장한 사실을 알린다.(말하기)
			oos.writeObject(100+"#"+nickName);
			//서버에 말을 한 후 들을 준비를 한다.
			SocketClientThread tct = new SocketClientThread(this);
			tct.start();
		} catch (Exception e) {
			//예외가 발생했을 때 직접적인 원인되는 클래스명 출력하기
			System.out.println(e.toString());
		}
	}

	
	

	@Override
	public void actionPerformed(ActionEvent ae) {
		/**
		 * 이 지점에서 닉네임을 읽어들이지 못하는 문제가 발생했다. -> 서버, 서버스레드에 대한 문제는 없다.
		 */
		
		Object obj = ae.getSource();
		String msg = jtf_msg.getText();
		
		
		 if(jbtn_send == obj)
		{
			try {
				oos.writeObject(201
						   +"#"+nickName
						   +"#"+msg);
				jtf_msg.setText("");
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
		 else if (obj == jbtn_font)
		 {
			 /**
			  * 구글참고
			  */
		        Color currentColor = jta_display.getForeground();
		        if (Color.RED.equals(currentColor)) {
		            jta_display.setForeground(Color.BLACK);
		        } else {
		            jta_display.setForeground(Color.RED);
		        }}
		 
		 
		else if(jtf_msg==obj) {
			try {
				oos.writeObject(201
						   +"#"+nickName
						   +"#"+msg);
				jtf_msg.setText("");
				
			} catch (Exception e) {
			}}

		
		else if (jbtn_del == obj) {
			/**
			 * 리팩토링 시작 
			 * 
			 */
			String del = "회원탈퇴.";
			try {
				oos.writeObject(210
						   +"#"+nickName
						   +"#"+del);
				jtf_msg.setText("");
			}
			catch (Exception e) {
				// TODO: handle exception
			}
			
			 deleteSelectedRow();
			
			
			 
		}
			
		 
		else if(jbtn_list == obj)
		{
			mbl = new MemberListFrame();
			
		}
		
		else if(jbtn_exit==obj) {
			try {

			    try {
			        oos.writeObject(210 + "#" + nickName + "#");
			    } catch (IOException e) {
			        e.printStackTrace();
			    }
			    
				logout();
				dispose();
			} catch (Exception e) {
				
			}
		}
		
		
		else if(jbtn_change == obj) {
			String afterName = JOptionPane.showInputDialog("변경할 대화명을 입력하세요.");
			if(afterName == null || afterName.trim().length()<1) {
				JOptionPane.showMessageDialog(this
				, "변경할 대화명을 입력하세요"
				, "INFO", JOptionPane.INFORMATION_MESSAGE);
				return;
			}
			try {
				oos.writeObject(202
						   +"#"+nickName
						   +"#"+afterName
						   +"#"+nickName+"의 대화명이 "+afterName+"으로 변경되었습니다.");
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
	}//////////////////////end of actionPerformed

	
	public void logout()
	{
		 int selectedRow = jtb.getSelectedRow();
		 LoginForm lf = new LoginForm();
		 DefaultTableModel model = (DefaultTableModel) jtb.getModel();
		 model.removeRow(selectedRow);
		 JOptionPane.showMessageDialog(this, "로그아웃 성공했습니다..", "Info", JOptionPane.INFORMATION_MESSAGE);
		 dispose();
	}
	
	// 클라이언트에서 회원 탈퇴 요청 메서드
//	public void requestLogout() {
//	    try {
//	        oos.writeObject(210 + "#" + nickName + "#");
//	    } catch (IOException e) {
//	        e.printStackTrace();
//	    }
//	}
	

	public void deleteSelectedRow() {
	    int selectedRow = jtb.getSelectedRow();
	    MemberDao dao = MemberDao.getInstance();
	    if (selectedRow < 0) {
	        JOptionPane.showMessageDialog(this, "삭제할 부분을 고르세요", "Info", JOptionPane.INFORMATION_MESSAGE);
	        return;
	    }

	    String nicknameToDelete = (String) jtb.getValueAt(selectedRow, 0);
	    //선택한 행에서 닉네임 데이터를 추출하여 nicknameToDelete 변수에 저장

	    int result = dao.deleteMemberByNickname(nicknameToDelete);

	    if (result > 0) {
	        DefaultTableModel model = (DefaultTableModel) jtb.getModel();
	        model.removeRow(selectedRow);
	        JOptionPane.showMessageDialog(this, "성공적으로 삭제됐습니다.", "Info", JOptionPane.INFORMATION_MESSAGE);
	        
	    } else {
	        JOptionPane.showMessageDialog(this, "삭제 실패했습니다..", "Error", JOptionPane.ERROR_MESSAGE);
	    }
	}
}

SocketClientThread.java

package com.soket.client;

import java.util.StringTokenizer;
import java.util.Vector;


public class SocketClientThread extends Thread {
	SocketClient tc = null;
	public SocketClientThread(SocketClient tc) {
		this.tc = tc;
	}
	/*
	 * 서버에서 말한 내용을 들어봅시다.
	 */
	public void run() {
		boolean isStop = false;
		while(!isStop) {
			try {
				String msg = "";//100#apple
				msg = (String)tc.ois.readObject();
				StringTokenizer st = null;
				int protocol = 0;//100|200|201|202|500
				if(msg !=null) {
					st = new StringTokenizer(msg,"#");
					protocol = Integer.parseInt(st.nextToken());//100
				}
				switch(protocol) {
					case 100:{//100#apple
						String nickName = st.nextToken();
						tc.jta_display.append(nickName+"님이 입장하였습니다.\n");
						Vector<String> v = new Vector<>();
						v.add(nickName);
						tc.dtm.addRow(v);
					}break;
					case 200:{
						
					}break;
					case 201:{
						String nickName = st.nextToken();
						String message = st.nextToken();
						tc.jta_display.append("["+nickName+"]"+message+"\n");
						tc.jta_display.setCaretPosition
						(tc.jta_display.getDocument().getLength());					
					}break;
					case 202:{
						String nickName = st.nextToken();
						String afterName = st.nextToken();
						String message = st.nextToken();
						//테이블에 대화명 변경하기
						for(int i=0;i<tc.dtm.getRowCount();i++) {
							String imsi = (String)tc.dtm.getValueAt(i, 0);
							if(nickName.equals(imsi)) {
								tc.dtm.setValueAt(afterName, i, 0);
								break;
							}
						}
						//채팅창에 타이틀바에도 대화명을 변경처리 한다.
						if(nickName.equals(tc.nickName)) {
							tc.setTitle(afterName+"님의 대화창");
							tc.nickName = afterName;
						}
						tc.jta_display.append(message+"\n");
					}break;
					
					case 210:{
						String nickName = st.nextToken();
						tc.jta_display.append(nickName+"님이 퇴장 하였습니다.\n");
						tc.jta_display.setCaretPosition
						(tc.jta_display.getDocument().getLength());
						for(int i=0;i<tc.dtm.getRowCount();i++) {
							String n =(String)tc.dtm.getValueAt(i, 0);
							if(n.equals(nickName)) {
								tc.dtm.removeRow(i);
							}
							/**
							 * 2개의 창을 띄운다고 가정했을 때 한쪽에서 삭제하면 다른 한쪽에서 회원탈퇴한 내용을 반영하고 싶은데 어떻게 해야돼?
							 */
						}
					}break;
				}////////////end of switch
			} catch (Exception e) {
				// TODO: handle exception
			}
		}////////////////////end of while
	}////////////////////////end of run
}

profile
아는만큼보인다.

0개의 댓글