Intro

이 글은 자바로 소켓 통신 프로그램을 만드는 방법에 대한 정보를 담은 글입니다.


사용할 클래스

  • ServerSocket

    • 서버 소켓을 생성하고 클라이언트의 연결을 대기하는 역할을 한다.
  • Socket

    • 클라이언트와 서버 간의 연결을 나타내며, 데이터를 주고받을 수 있는 통신 채널.
  • InputStream

    • 소켓에서 들어오는 바이트 데이터를 읽기 위한 기본 스트림.
  • InputStreamReader

    • 바이트 데이터를 문자 데이터로 변환하는 스트림.
  • BufferedReader

    • 문자 데이터를 효율적으로 읽기 위해 버퍼링하는 클래스입니다. 줄 단위(readLine)로 데이터를 읽는 기능을 제공한다.
  • PrintWriter

    • 데이터를 텍스트 형식으로 출력하며, 자동 플러시 기능을 제공하는 출력 스트림.

 


서버(Server) 코드

package javachat;

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

public class MyServer {

    public MyServer() {
        
    }
    
    private static final int SERVER_PORT = 9999;
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        ServerSocket sk = null;
        HashMap<String, String> map = new HashMap<String, String>();
        map.put("sk-choi", "가장 잘생긴 꽃미남");
        map.put("Java", "객체지향 언어");
        
        try {
            sk = new ServerSocket(SERVER_PORT);
            System.out.println("서버 실행");
            
            while (true) {
                Socket s = sk.accept(); //기다리기
                System.out.println(sk.getInetAddress() + "[클라이언트 접속]"); // 해당 서버 소켓의 로컬 주소 리턴
                BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
                PrintWriter pw = new PrintWriter(s.getOutputStream(), true); // 버퍼, 개행, 자동 플러시(true)
                String msg = "";
                
                //소켓 생성을 하고 언제든지 받을 준비 되었어요 → 연결 정보 출력할게요 
                // → 보낸 데이터 읽을 준비 됐어요. 근데 읽기 효율을 위해 버퍼에 담아서 읽을게요 → 출력할 준비 됐어요
                
                while((msg = br.readLine()) != null) {
                    System.out.println("[클라이언트 메세지 수신]" + msg);
                    boolean ans = false;
                    String answer = null;
                    for (String key : map.keySet()) {
                        ans = msg.contains(key);
                        if (ans) {
                            System.out.println(map.get(key));
                            answer = map.get(key);
                            break;
                        }
                    }
                    if (ans == false) {
                        answer = "다시 물어바주세요";
                    }
                    pw.println(answer);
                    pw.println("서버응답 수신 완료");
                }	
                
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

서버 코드의 특징

서버는 소켓 생성을 통해 클라이언트의 요청을 받을 준비를 하고, 클라이언트의 요청이 들어오면 요청에 맞게 처리한다.

클라이언트와의 연결이 지속되는 동안 계속 작동해야 하므로 무한 루프로 동작해야 한다.

서버의 프로세스는 대략 다음과 같다.

==소켓 생성을 하고 언제든지 받을 준비 되었어요 → 연결 정보 출력할게요== 

==→ 보낸 데이터 읽을 준비 됐어요. 근데 읽기 효율을 위해 버퍼에 담아서 읽을게요 → 출력할 준비 됐어요==


클라이언트(Client) 코드

package javachat;

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

public class MyClient {

    private static final String SERVER_IP = "127.0.0.1";
    private static final int SERVER_PORT = 9999;
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Socket s = null;
        
        try {
            s = new Socket(SERVER_IP, SERVER_PORT);
            System.out.println("서버 연결 완료");
            
            Scanner sc = new Scanner(System.in);
            PrintWriter pw = new PrintWriter(s.getOutputStream(), true);// 버퍼+개행, 자동 플러시 자동화 
            InputStream is = s.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String sendmsg = null;
            
            //글자 전송할 소켓 가져올게요 → 글자 써서 전송할게요 → 전송된 거 데이터 읽을게요 → 읽은 데이터 문자로 바꿀게요 → 효율적인 입력을 위해 버퍼링할게요
            
            while(true) {
                sendmsg = sc.nextLine(); // 콘솔 입력 받기
                
                if (sendmsg.equalsIgnoreCase("exit")) {
                    System.out.println("클라이언트 종료");
                    break;
                }
                pw.println(sendmsg);
                
                String rsvmsg = br.readLine();
                System.out.println("[서버 메세지 수신]" + rsvmsg);
            }
        } catch(UnknownHostException e) {
            e.printStackTrace();
        } catch(IOException e) {
            e.printStackTrace();
        }
    }
}

 

클라이언트는 서버에게 요청을 한다. 

클라이언트도 서버에게 특정 조건 전에는 계속 요청을 해야 하므로 무한 루프로 작동한다.

클라이언트의 프로세스는 대략 다음과 같다.

==글자 전송할 소켓 가져올게요 → 글자 써서 전송할게요 → 전송된 거 데이터 읽을게요==

==→ 읽은 데이터 문자로 바꿀게요 → 효율적인 입력을 위해 버퍼링할게요==

 

태그:

카테고리:

업데이트:

댓글남기기