새소식

인기 검색어

개인공부/Java

java 소켓 멀티캐스트 && JFrame

  • -

아이디 중복 검사

해당 닉네임을 사용하는 클라이언트가 서버에 접속 중일 경우 유효성 검사에 의해 접속 불가 처리를 구현하였습니다.

단어 필터링 01
단어 필터링 02

클라이언트가 필터링 단어를 지정하면 해당 단어는 특수문자 처리가 되는 것을 확인할 수 있습니다

 

 

 

 

 

 

귓속말 01
귓속말 02
귓속말 03

귓속말할 대상의 대화명을 입력 후 대화 내용을 입력하면 그 클라이언트에게만 메시지를 전송한다

채팅방 테마 설정

채팅방의 테마를 설정하는 기능을 구현 하였다

Client.java

package Multicast;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.Socket;

class ClientExample4 extends JFrame implements ActionListener {
    CardLayout card = new CardLayout();
    Login login = new Login();
    WaitRoom wr = new WaitRoom();
    FilterUi ui = new FilterUi();

    public ClientExample4() {
        setLayout(card);
        add("LOGIN", login);
        add("WR", wr);
        setSize(1024, 950);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        login.b1.addActionListener(this);
        login.b2.addActionListener(this);
        wr.b3.addActionListener(this);//waitRoom에서 차단하기 버튼
        wr.tf.addActionListener(this);
        wr.b4.addActionListener(this);//waitRoom에서 필터링 추가하기 버튼

    }

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

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println(e.getSource());
        if (e.getSource() == login.b1) {
            String name = login.pf.getText();
            String sex = "";
            if (login.rb1.isSelected())
                sex = "남자";
            else
                sex = "여자";
            connection(name, sex);
        }
    }

    private void connection(String name, String sex) {
        try {
            // 서버와 연결
            Socket socket = new Socket("localhost", 9002);


            Thread thread2 = new ReceiverThread(socket, wr, login, ui);
            thread2.start();

            Thread thread1 = new SenderThread(socket, name, sex, wr, login, ui);
            thread1.start();
            // card.show(getContentPane(), "WR");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

Client의 senderThread.java

package Multicast;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

class SenderThread extends Thread {
    Socket socket;
    String name, sex, pos;
    WaitRoom wr;
    PrintWriter writer;
    Login login;
    FilterUi ui;


    public SenderThread(Socket socket, String name, String sex, WaitRoom wr, Login login, FilterUi ui) {
        this.socket = socket;
        this.name = name;
        this.sex = sex;
        this.wr = wr;
        this.login = login;
        this.ui = ui;
        wr.tf.addKeyListener(new keyEventHandler());
        wr.b6.addActionListener(new ActionHandler());//waitRoom에서 나가기 버튼
        wr.b1.addActionListener(new ActionHandler());//waitRoom에서 추방건의 버튼
        ui.tf.addKeyListener(new KeyEventHandler2());
        wr.b5.addActionListener(new ActionHandler());
    }

    public void run() {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            writer = new PrintWriter(socket.getOutputStream());

            // 제일 먼저 서버로 대화명 송신한다.
            writer.println(name + "##" + sex + "##");
            writer.flush();

            // 키보드로 입력된 메시지를 서버로 송신
            while (true) {
                String str = reader.readLine();
                if ("/!".startsWith(str)) {
                    continue;
                }
                if (str.equals("bye"))
                    break;
                writer.println(str);
                writer.flush();
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            try {
                socket.close();
            } catch (Exception ignored) {
            }
        }
    }


    class keyEventHandler extends KeyAdapter {//이너클래스

        @Override
        public void keyPressed(KeyEvent e) {
//            System.out.println("wr tf 이벤트 액션 start");
            if (e.getKeyChar() == KeyEvent.VK_ENTER) {//엔터를 눌렀을 경우
                String StateCode = "50";
                System.out.println(StateCode + "##" + wr.tf.getText());
                if ("/!".startsWith(wr.tf.getText())) {
                } else {
                    writer.println(wr.tf.getText());
                    writer.flush();
                    wr.tf.setText("");
                }
            }
        }
    }

    class KeyEventHandler2 extends KeyAdapter {
        public void keyTyped(KeyEvent e) {
            if (e.getKeyChar() == KeyEvent.VK_ENTER) {
                if (ui.tf.getText().length() < 2) {
                    System.out.println("두자리 이상만 가능");
                } else {
                    ReceiverThread.addFilter(ui.tf.getText());
                    writer.println("/!" + ui.tf.getText() + "!/");
                    writer.flush();
                    ui.tf.setText("");
                    ui.disp();
                }
            }
        }
    }

    class ActionHandler implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == wr.b6) {
                writer.println("exit##");
                writer.flush();
                wr.ta.setText("");//textarea 초기화
                wr.setVisible(false);
                login.setVisible(true);
            } else if (e.getSource() == wr.b6) {
                String uname = JOptionPane.showInputDialog("건의할 대상자의 닉네임을 입력하세요");
                writer.println("exP##uname");
                writer.flush();
            } else if (e.getSource() == wr.b5) {
                String resultStr = null;
                String totalStr = null;
                resultStr = JOptionPane.showInputDialog("귓속말 할 대상을 입력해주세요.");
                totalStr = JOptionPane.showInputDialog("내용을 입력하세요");
                writer.println("Whispering##" + resultStr + "##" + totalStr);
                writer.flush();
            }

        }
    }
}

Client의 ReceiverThread.java

package Multicast;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

class ReceiverThread extends Thread {
    Socket socket;
    WaitRoom wr;
    ArrayList<String> banName = new ArrayList<String>();
    ActionEventEx block = new ActionEventEx();
    Login login;
    static ArrayList<String> filter = new ArrayList<String>();
    FilterUi ui;

    ReceiverThread(Socket socket, WaitRoom wr, Login login, FilterUi ui) {
        this.socket = socket;
        this.wr = wr;
        this.login = login;
        this.ui = ui;
        block.setVisible(false);
        wr.b2.addActionListener(new ActionHandler());//waitRoom에서 나가기 버튼
        block.b1.addActionListener(new ActionHandler());
        wr.b4.addActionListener(new ActionHandler());
    }

    public void run() {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while (true) {
                //서버로부터 수신된 메시지를 모니터로 출력
                String str = reader.readLine();
                System.out.println("받은문자 : " + str);
                if (str.endsWith("!/")) {
                    continue;
                } else {
                    str = checkFilter(str);
                }
                StringTokenizer st = new StringTokenizer(str, "##");
                String[] result = str.split("##");
                if (result[0].equals("50")) {
                    if (result[1].contains("들어오셨습니다") || result[1].contains("나가셨습니다")) {
                        if (wr.model2.getRowCount() > 0) {
                            for (int i = wr.model2.getRowCount() - 1; i > -1; i--) {
                                wr.model2.removeRow(i);
                            }
                            wr.ta.append(result[1] + "\n");
                        }
                    } else {
                        if (!banName.contains(result[1].substring(0, result[1].indexOf(">")))) {
                            wr.ta.append(result[1] + "\n");
                        }
                    }
                } else if (result[0].equals("100")) {

                    System.out.println("클라이언트 정보 : " + result[1]);
                    System.out.println("클라이언트 정보 : " + result[2]);
                    String[] row = new String[2];
                    row[0] = result[1];
                    row[1] = result[2];
                    wr.model2.addRow(row);
                } else if (str.equals("true")) {
                    JOptionPane.showMessageDialog(null, "중복된 아이디입니다.\n아이디를 다시 입력해주세요.");
                } else if (str.equals("false")) {
                    wr.setVisible(true);
                    login.setVisible(false);
                } else if (result[0].equals("whisp")) {
                    System.out.println("ReceiverThreadwHISP : " + Arrays.toString(result));
                    wr.ta.append("========================================\n");
                    wr.ta.append(result[1] + "님의 귓속말 ==>> " + result[2] + "\n");
                    wr.ta.append("========================================\n");
                }
                if (str == null)
                    break;
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    class ActionHandler implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == wr.b2) {
                block.setVisible(true);
            } else if (e.getSource() == block.b1) {
                banName.clear();
                String result = block.ta.getText();
                String[] rs = result.split("\n");
                banName = new ArrayList<>(Arrays.asList(rs));
                System.out.println("banName 리스트 : " + banName);
                block.setVisible(false);
            } else if (e.getSource() == wr.b4) {
                ui.disp();
                ui.setVisible(true);
            }
        }
    }

    public static void addFilter(String str) {
        if (!filter.contains(str)) {
            filter.add(str);
            System.out.println(filter + "추가되었습니다.");
        } else
            System.out.println("이미 추가된 단어입니다.");
    }

    public String checkFilter(String str) {
        for (String s : filter) {
            if (str.contains(s))
                str = str.replace(s, "**");
        }
        return str;
    }
}

Server.java

package Multicast;

import java.net.ServerSocket;
import java.net.Socket;

class ServerExample4 {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(9002);
            while (true) {
                Socket socket = serverSocket.accept();
                Thread thread = new PerClinetThread(socket);
                thread.start();
            }
        }
        catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

PerClientThread.java

// 각 클라이언트 접속에 대해 하나씩 작동하는 스레드 클래스

package Multicast;

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

class PerClinetThread extends Thread {

    // ArrayList 객체를 여러 스레드가 안전하게 공유할 수 있는 동기화된 리스트로 만듭니다.
    static List<PrintWriter> list = Collections.synchronizedList(new ArrayList<PrintWriter>());
    static ArrayList<Clients> clientsList = new ArrayList<Clients>();
    static int Expulsion, EpCOunt;//강퇴 찬성 횟수, 강퇴 찬반대 신청 횟수
    Socket socket;
    PrintWriter writer;
    Clients client;

    PerClinetThread(Socket socket) {
        this.socket = socket;
        try {
            writer = new PrintWriter(socket.getOutputStream());
            list.add(writer);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    public void run() {
        String result = null, id = null, name = null, sex = null;

        try {
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(socket.getInputStream()));

            // 수신된 첫번째 문자열을 대화명으로 사용하기 위해 저장
            result = reader.readLine();
            StringTokenizer st = new StringTokenizer(result, "##");
            name = st.nextToken();
            sex = st.nextToken();
            String flag = Validation(name);
            if (flag.equals("true")) {
                Exception ex = new Exception("고의로 발생시켰음");
                throw ex;
            }

            client = new Clients(name, sex, writer);
            clientsList.add(client);
            sendAll("50",
                    "!" + name + "님이 들어오셨습니다");
            sendConnectList();
            while (true) {
                String str = reader.readLine();
                String[] rs = str.split("##");
                System.out.println("서버에서 받은 msg : " + str);
                if (rs[0] == null) {
                    break;
                } else if (rs[0].equals("exit")) {//클라이언트가 나가기 버튼을 누른 경우
                    break;
                } else if (rs[0].equals("exP")) {//클라이언트가 추방건의를 누른 경우
                    sendAll("Election", "Election");//모든 클라이언트들에게 메세지 전송
                } else if (rs[0].equals("Whispering")) {//클라이언트가 추방건의를 누른 경우
                    System.out.println("서버에서 귓속말 내용 : " + rs[0] + " " + rs[1] + " " + rs[2] + " ");
                    sendWhispering(rs[1], rs[2]);//모든 클라이언트들에게 메세지 전송
                    continue;
                }

                sendAll("50", name + ">" + str);  // 수신된 메시지 앞에 대화명을 붙여서 모든 클라이언트로 송신

            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            list.remove(writer);
            sendAll("50", "!" + name + "님이 나가셨습니다"); // 사용자가 채팅을 종료했다는 메시지를 모든 클라이언트로 보냅니다.
            clientsList.remove(client);
            sendConnectList();
            try {
                socket.close();
            } catch (Exception ignored) {
            }
        }
    }

    // 서버에 연결되어 있는 모든 클라이언트로 똑같은 메시지를 보냅니다.
    private void sendAll(String StateCode, String str) {

        for (PrintWriter writer : list) {//현재 접송중인 모든 유저에게 msg 전송
            writer.println(StateCode + "##" + str);
            writer.flush();
        }
    }

    private void sendConnectList() {
        for (Clients clist : clientsList) {//현재 접송중인 모든 유저에게 msg 전송
            String StateCode = "100";
            String str = clist.getName() + "##" + clist.getSex();
            System.out.println(str);
            sendAll(StateCode, str);
        }
    }

    private void sendWhispering(String name, String msg) {
        System.out.println("sendWhisperingMethod : " + name + " : " + msg);
        int cnt = 0;
        for (Clients xx : clientsList) {
            if (xx.getName().equals(name)) {
                cnt++;
                xx.getWriter().println("whisp##"+this.client.getName()+"##"+msg);
                xx.getWriter().flush();
            }
        }
        System.out.println("반복횟수 : " + cnt);
    }

    private String Validation(String name) {
        String flag = "false";
        for (Clients xx : clientsList) {
            if (xx.getName().equals(name)) {
                flag = "true";
            }
//            else{
//                writer.println("12");
//                writer.flush();
//            }

        }
        System.out.println(flag);
        writer.println(flag);
        writer.flush();
        return flag;
    }
}

 


UI.Class

 

Login.java

package Multicast;

import javax.swing.*;
import java.awt.*;

public class Login extends JPanel{
    private Image back;
    private JLabel la1,la2,la3;
    JTextField tf;       //default로 잡힌 이유는 다른 클래스에서 사용해야 하기 때문에
    JTextField pf;   //default로 잡힌 이유는 다른 클래스에서 사용해야 하기 때문에
    JButton b1,b2;      //default로 잡힌 이유는 다른 클래스에서 사용해야 하기 때문에
    JRadioButton rb1, rb2;

    public Login()
    {
        //이미지 정보 읽기
        back=Toolkit.getDefaultToolkit().getImage("C:\\Users\\smreo\\Pictures\\Saved Pictures\\back.jpg");
        setLayout(null); //직접 배치

//        //로그인 부분 아이디와 아이디 칠 textField
//        la1=new JLabel("아이디",JLabel.RIGHT);
//        la1.setBounds(745, 730, 80, 30);
//        tf=new JTextField();
//        tf.setBounds(830, 730, 150, 30);
//        add(la1); add(tf);

        //로그인 부분 비밀번호와 비밀번호 칠 textField
        la2=new JLabel("대화명",JLabel.RIGHT);
        la2.setBounds(745, 765, 80, 30);
        pf=new JTextField();
        pf.setBounds(830, 765, 150, 30);
        add(la2); add(pf);

        rb1=new JRadioButton("남자");
        rb2=new JRadioButton("여자");
        ButtonGroup bg=new ButtonGroup();
        bg.add(rb1); bg.add(rb2);
        rb1.setSelected(true);
        la3=new JLabel("성별",JLabel.RIGHT);
        la3.setBounds(745, 800, 80, 30);
        rb1.setBounds(830, 800, 70, 30);
        rb2.setBounds(910, 800, 70, 30);
        rb1.setOpaque(false);
        rb2.setOpaque(false);
        add(la3); add(rb1); add(rb2);

        b1 = new JButton("로그인");
        b2 = new JButton("취   소");
        JPanel p = new JPanel(); //패널을 배치하는 이유, 가운데 맞추기 어려워서 패널로 잡아준다
        p.add(b1);
        p.add(b2);
        p.setOpaque(false); // setOpaque -투명모드
        p.setBounds(740, 850, 235, 35);
        add(p);
    }

    @Override
    protected void paintComponent(Graphics g) {
        // TODO Auto-generated method stub
        g.drawImage(back, 0, 0, getWidth(), getHeight(), this);
    }

    public static void main(String[] args) {

    }
}

WaitRoom.java

package Multicast;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class WaitRoom extends JPanel {
    JTable table1, table2;
    DefaultTableModel model1, model2;
    JTextField tf;
    JTextArea ta;
    JButton b1, b2, b3, b4, b5, b6;
    JScrollBar bar;


    public WaitRoom() {
//        String[] col1 = {"방이름", "공개/비공개", "인원"};
//        String[][] row1 = new String[0][3];
//
//        model1 = new DefaultTableModel(row1, col1);
//        table1 = new JTable(model1);
//        JScrollPane js1 = new JScrollPane(table1);

        String[] col2 = {"대화명", "성별"};
        String[][] row2 = new String[0][2];

        model2 = new DefaultTableModel(row2, col2);
        table2 = new JTable(model2);
        JScrollPane js2 = new JScrollPane(table2);

        ta = new JTextArea();
        ta.setEditable(false);
        JScrollPane js3 = new JScrollPane(ta);
        bar = js3.getVerticalScrollBar();

        tf = new JTextField();

        b1 = new JButton("추방건의");
        b2 = new JButton("차단하기");
        b3 = new JButton("채팅방 설정");
        b4 = new JButton("단어 필터링");
        b5 = new JButton("귓속말 보내기");
        b6 = new JButton("나가기");


        // 배치
        setLayout(null);
        //     js1.setBounds(10, 15, 600, 500);
        //       js2.setBounds(10, 520, 600, 350);
        js2.setBounds(10, 15, 600, 500);
        //      add(js1);
        add(js2);

        js3.setBounds(615, 15, 390, 465);
        add(js3);

        tf.setBounds(615, 480, 390, 30);
        add(tf);

        JPanel p = new JPanel();
        p.setLayout(new GridLayout(3, 2, 5, 5));
        p.add(b1);
        p.add(b2);
        p.add(b3);
        p.add(b4);
        p.add(b5);
        p.add(b6);
        p.setBounds(615, 523, 390, 350);
        add(p);
        ButtonAction();
    }

    public void ButtonAction() {
        b6.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new Login();
                setVisible(false);//창 안보이게 하기
            }
        });

        b3.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new Change();
            }
        });
//귓속말말

    }

    class Change extends Frame {
        JCheckBox cb1, cb2, cb3, cb4, cb5, cb6;
        JButton bb1, bb2;

        public Change() {

            JPanel p = new JPanel();
            p.setLayout(null);
            this.add(p);
            setSize(400, 400);
            setVisible(true);
            cb1 = new JCheckBox("Dark");
            cb2 = new JCheckBox("Orange");
            cb3 = new JCheckBox("Red");
            cb4 = new JCheckBox("Green");
            cb5 = new JCheckBox("Yellow");
            cb6 = new JCheckBox("Bold");

            bb1 = new JButton("확인");
            bb2 = new JButton("취소");

            bb1.setBounds(90, 300, 70, 30);
            bb2.setBounds(240, 300, 70, 30);
            cb1.setBounds(70, 40, 90, 30);
            cb2.setBounds(180, 40, 90, 30);
            cb3.setBounds(280, 40, 90, 30);
            cb4.setBounds(70, 80, 90, 30);
            cb5.setBounds(180, 80, 90, 30);
            cb6.setBounds(120, 200, 70, 30);

            p.add(bb1);
            p.add(bb2);
            p.add(cb1);
            p.add(cb2);
            p.add(cb3);
            p.add(cb4);
            p.add(cb5);
            p.add(cb6);

            bb1.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent arg0) {

                    if (cb1.isSelected()) {
                        ta.setBackground(Color.BLACK);
                        ta.setForeground(Color.PINK);
                    } else if (cb2.isSelected()) {
                        Font font = new Font("digital-7", Font.BOLD, 30);
                        ta.setBackground(Color.ORANGE);
                        ta.setForeground(Color.BLACK);
                    } else if (cb3.isSelected()) {
                        ta.setBackground(Color.RED);
                        ta.setForeground(Color.WHITE);
                    } else if (cb4.isSelected()) {
                        ta.setBackground(Color.GREEN);
                        ta.setForeground(Color.YELLOW);
                    } else if (cb5.isSelected()) {
                        ta.setBackground(Color.YELLOW);
                        ta.setForeground(Color.BLACK);
                    } else if (cb6.isSelected()) {
                        Font font = new Font("Serif", Font.BOLD, 15);
                        tf.setFont(font);
                        ta.setFont(font);
                    }
                    dispose();
                }

            });

            bb2.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    dispose();
                }
            });

        }
    }
}

FilterUi.java

package Multicast;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class FilterUi extends Frame implements ActionListener {
    Panel p1, p2, p3;
    TextField tf;
    static TextArea ta;
    Button b1, b2;

    public FilterUi() {
        super("필터링");
        p1 = new Panel();
        p2 = new Panel();
        p3 = new Panel();
        tf = new TextField(35);
        ta = new TextArea(10, 35);
        b1 = new Button("Delete");
        b2 = new Button("Exit");
        p1.add(tf);
        p2.add(ta);
        p3.add(b1);
        p3.add(b2);
        add("North", p1);
        add("Center", p2);
        add("South", p3);

        b1.addActionListener(this);
        b2.addActionListener(this);
        addWindowListener(new WindowAdapter() {
            public void WindowClosing(WindowEvent e) {
                dispose();
                dispose();
            }
        });
        setBounds(300, 200, 300, 300);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String str = e.getActionCommand();
        if (ReceiverThread.filter.contains(str)) {
            System.out.println(tf.getText());
            tf.requestFocus();
            disp();
        } else if (str.equals("Delete")) {
            ReceiverThread.filter.remove(ReceiverThread.filter.indexOf(tf.getText()));
            tf.setText("");
            disp();
        } else if (str.equals("Exit")) {
            dispose();
        }

    }

    public static void disp() {
        ta.setText("");
        for (int i = 0; i < ReceiverThread.filter.size(); i++) {
            ta.append(ReceiverThread.filter.get(i) + "\n");
        }
    }

    public static void main(String[] args) {
        FilterUi ui = new FilterUi();
    }
}

Final.zip
0.02MB

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.