[자바] TCP 소켓 프로그래밍을 통한 1:1 채팅 구현하기

Heon·2023년 7월 5일
0

자바

목록 보기
2/4

자바에서 네트워킹을 공부하면서 tcp/ip에 대해 학습하던 중 이를 통해 채팅창을 구현해보기로 하였다.

제목에서 보았듯이 TCP 프로토콜을 활용하므로 필요한 클래스는 Socket과 ServerSocket을 이용할 예정이다
따라서 Server와 Client를 구분해야 할 것이고 TCP를 통한 서버 클라이언트의 통신은 서버 측에서 클라이언트의 요청을 기다리고 클라이언트가 연결을 요청하면 그제서야 두 클래스가 정상적으로 실행될 것이다.

다시 말하지만, 서버 부터 실행해야 한다는 것을 잊지말자.

이해가 안 간다다면 tcp 통신에 대해 학습을 먼저 권한다.

서버 코드

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

public class TcpIpServer {
    public static void main(String args[]) {
        ServerSocket serverSocket = null;
        Socket socket = null;

        try {
            // 서버소켓을 생성하여 7777번 포트와 결합시킨다.
            serverSocket = new ServerSocket(7777);
            System.out.println("서버가 준비되었습니다");

            socket = serverSocket.accept();
            System.out.println("[서버의 채팅창]");

            Sender   sender   = new Sender(socket);
            Receiver receiver = new Receiver(socket);

            sender.start();
            receiver.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    } // main
} // class

class Sender extends Thread {
    Socket socket;
    DataOutputStream out;
    String name;

    Sender(Socket socket) {
        this.socket = socket;
        try {
            out = new DataOutputStream(socket.getOutputStream());
            name = "["+socket.getInetAddress()+":"+socket.getPort()+"]";
        } catch(Exception e) {}
    }

    public void run() {
        Scanner scanner = new Scanner(System.in);
        while(out!=null) {
            try {
                out.writeUTF(name+scanner.nextLine());
            } catch(IOException e) {}
        }
    } // run()
}

class Receiver extends Thread {
    Socket socket;
    DataInputStream in;

    Receiver(Socket socket) {
        this.socket = socket;
        try {
            in = new DataInputStream(socket.getInputStream());
        } catch(IOException e) {}

    }

    public void run() {
        while(in!=null) {
            try {
                System.out.println(in.readUTF());
            } catch(IOException e) {}
        }
    } // run
}

서버 코드 설명

serverSocket = new ServerSocket(7777);

다음 클라이언트 코드에서 7777번 포트로 접속하기 위해 임의의 숫자를 입력했다.
0~65535 범위에서 임의의 포트 번호를 사용해도 되지만, 보통 1023번 이하의 포트는 FTP나 Telnet과 같은 기존 통신 프로토콜에 의해 사용되는 경우가 많기 때문에 1023번 이상의 포트 번호를 골라 사용해야 하자.

class Receiver extends Thread { ... }
class Sender extends Thread { ... }

채팅창에선 채팅입력을 하거나, 상대측에서 입력한 채팅을 수신하거나 둘 중 하나만 골라서 하지 않는다. 두 기능이 동시에 이루어져야 한다. 이 말은 두 쓰레드가 동시에 실행되어야 한다는 뜻이고 수신자와 발신자를 따로 쓰레드로 처리해야 한다는 의미이다. 쓰레드 동작에 대해선 따로 설명을 생략하겠다. 궁금하면 찾아보기로 하자.

클라이언트 코드

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

public class TcpIpClient {
    public static void main(String args[]) {
        try {
            String serverIp = "127.0.0.1";

            // 소켓을 생성하여 연결을 요청한다.
            Socket socket = new Socket(serverIp, 7777);

            System.out.println("서버에 연결되었습니다");
            System.out.println("[클라이언의 채팅창]");
            Sender sender = new Sender(socket);
            Receiver receiver = new Receiver(socket);

            sender.start();
            receiver.start();
        } catch(ConnectException ce) {
            ce.printStackTrace();
        } catch(IOException ie) {
            ie.printStackTrace();
        } catch(Exception e) {
            e.printStackTrace();
        }
    } // main
} // class

클라이언트 코드 설명

서버에 비해 매우 간단하다.

String serverIp = "127.0.0.1";
// 소켓을 생성하여 연결을 요청한다.
Socket socket = new Socket(serverIp, 7777);

테스트 하기 위한 임의의 Ip주소를 설정하고 서버에서 설정한 포트 번호 7777로 연결을 요청한다

다음으로 실행하는 법에 설명할 건데, 저의 경우 같은 패키지에 있어서 sender와 receiver를 따로 구현하지 않고 가져와서 사용했지만 IDE를 여러 개 열어서 실행할 경우 알아서 복붙으로 가져오자.

실행 방법

서버와 클라이언트를 모두 실행해야 한다. 인텔리제이 IDE에서 다중 실행 설정하기 귀찮으면 그냥 인텔리제이든 이클립스든 2개 열어서 각각 실행해도 정상적으로 작동한다.
인텔리 제이 다중 실행은 다음 글을 참고하자.
https://balabala.tistory.com/25

설정이 끝났다면 서버를 먼저 실행시켜보자.

다음과 같이 클라이언트의 요청을 기다리고 있다.

이제 클라이언트를 실행시켜보자.

이미지1_설명 이미지2_설명
자 이제 클라이언트에서 연결 요청이 정상적으로 되면 클라이언트와 서버의 채팅창이 개설됨을 확인할 수 있을 것이다. 대화를 시작해보자.
이미지1_설명 이미지2_설명

다음과 같이 정상적으로 대화가 정상적으로 잘 작동된다.

다음 글로는 이를 응용하여 멀티채팅방을 만들어 보겠습니다.

profile
코딩일기

0개의 댓글