Purple Bobblehead Bunny

Backend/JAVA

[JAVA] ServerSocket

준영어린이 2022. 5. 2. 16:56

 

Socket 

 

JAVA에서 서버 프로그램을 개발할 때 쓰이는 클래스

Socket 클래스는 client에서 서버로 접속 하거나 Server에서 accept 하는데 필요한 클래스이다.

원격지에 있는 프로그램 간 연결에 사용한다.

 

 

 

Socket 프로그래밍 단계를 나타낸다

 

 

 

Socket 관련 클래스 / 함수

 

· Socket

 클라이언트가 서버에 연결요청에 사용

 

· SocketServer

 클라이언트의 연결요쳥을 받아 세션을 형성

 

· InputStream()

  데이터를 받기 위해서 사용되는 함수

 

· OutputStream()

   데이터를 보내기 위해서 사용되는 함수

 

 

 

 

ServerSocket, Socket 클래스의 주요 메서드

 

 

메서드 설명
Socket accept() · 클라이언트의 Socket 객체가 생성될 때 까지 블로킹 되는 메서드
· 클라이언트의 Socket객체가 생성돠면 서버에서 클라이언트와 
  통신할 수 있는
 Socket 객체 반환
void close() · ServerSocket 객체 닫기
int getLocalPort() · ServerSocket 객체가 청취 하고 있는 포트번호를 반환
int getSoTimeout() · ServerSocket 클래스의 accept()메서드가 유효할 수 있는 기간을
  밀리세컨드단위로 반환
· 값이 0이면 무한대를 의미
boolean isClosed() · ServerSocket객체의 닫힌 상태를 반환
· ServerSocket이 닫힌 경우 true 반환을 하고
  그렇지 않은 경우 false 반환
boolean isBound() 서버 소켓 객체가 포트에 바인딩 되었는지 여부를 알려준다
void setSoTimeout(int timeout) · ServerSocket클래스의 accept()메서드가 유효할 수 있는 시간을
  밀리세컨드로 설정
· 설정된 시간이 지나면 java.net.SocketTimeoutException예외 발생 후
  예외가 발생하더라도 ServerSocket 객체는 계속 유효
BufferedReader 서버에 메세지를 보낸다. (BufferedWriter)
BufferedWriter 서버가 보낸 메세지를 출력한다. (BufferedReader)

 

accept()

Socket accept() throws IOException, SecurityException;

· accept() 메서드는 무한루프로 처리한다

· 클라이언트의 TCP 요청이 오면 accept() 메서드를 통해 Socket 객체를 생성한 후 다른 클라이언트의

  TCP 요청을 기다리게 되므로 accept() 메서드를 무한루프로 처리를 해야 한다.

 

스레드 미사용 예제

 

Server

 

//------ 1 소켓통신을 사용하기 위해 ServerSocket 객체 생성
//         서버소켓을 가지고 클라이언트의 소켓 접속을 기다림
ServerSocket server = new ServerSocket(7777); 
System.out.println("접속 대기...");

//------ 2 ServerSocket 객체의 accept()메서드 호출
//         Client로부터 연결요청이 올 때 까지 기다린다. --> main 스레드 wait
//------ 3 연결 요청이 들어오면 새로운 Socket 객체를 생성하여 Client의 Socket과 연결한다
Socket socket = server.accept();
// 이 후는 클라이언트와 연결된 후의 작업을 진행한다.

System.out.println("주소 : " + socket.getInetAddress());  // toString() Overriding

//------ 4 Socket객체의 Stream객체(InputStream, OutputStream)를 이용하여 메세지를 주고 받는다.
//         OutputStream 객체를 구성하여 전송
//         접속한 Socket의 getOutputStream()메서드를 이용하여 구한다.
OutputStream out = socket.getOutputStream();
DataOutputStream Dout = new DataOutputStream(out);
//----->   OutputStreamReader도 사용 가능

//------   메세지 보내기
dos.writeUTF("Hello World");  
System.out.println("Hello");

//------ 5 사용이 완료된 소켓은 close()메서드를 이용하여 종료 처리
Dout.close();
server.close();
//------   소켓도 스트림처럼 사용 후에 닫아줘야 한다.

 

Client

 

String serverIp = "192.168.5.50"; 

System.out.println(serverIp + " 서버에 접속 중입니다.");

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

//------ 2 연결이 정상적으로 이루어지면 생성된 소켓 객체를 이용하여 서버와 메세지를
//         주고받는다
//         생성된 소켓으로부터 스트림(InputStream, OutputStream)객체를 가져와 이용
System.out.println("연결 완료");

// 서버에서 보내온 메세지 받기
// 메세지를 받기 위해 InputStream 객체 생성
// Socket의 getInputStream() 메서드 이용
InputStream in = socket.getInputStream();
DataInputStream Din = new DataInputStream(in);

// 서버로부터 받은 메세지 출력
System.out.println(Din.readUTF());

System.out.println("연결종료");

//------ 3 사용 완료 된 소켓은 close() 메서드로 종료 처리
Din.close();
socket.close();

 


스레드 사용 예제

 

Sender , 소켓을 통해 메세지를 보내는 역할

 

public class Sender extends Thread {
  private DataOutputStream Dos;
  private String name;
  
  public Sender(Socket socket) {
      name = "[" + socket.getInetAddress() + " : " + socket.getLocalPort() + "]";
      
      try {
          dos = new DataOutputStream(socket.getOutputStream());
     }catch(Exception e){
          e.printStackTrace();
     }
}


@Override
public void run() {
    Scanner input = new Scanner(System.in);
    while (dos != null) { // 무한 루프
        try {         //scanner --> 엔터치기 전 까지 block
           dos.writeUTF(name + " >>> " + input.nextLine());
       }catch(Exception e){ 
       e.printStackTrace();
       }
     }
     input.close();
   } 
}

 

Receiver , 소켓에서 메세지를 받아 화면에 출력하는 역할

 

public class Receiver extends Thread {
   private Socket socket;
   private DataInputStream Dis;
   
   public Receiver(Socket socket) {
     this.socket = socket;
     
     try {
       dis = new DataInputStream(socket.getInputStream());
    }catch (IOException e) {
     e.printStackTrace();
    }
}

@Override
public void run() {
   while(dis != null) {
     try {
       System.out.println(dis.readUTF());
       // -> Sender에서 writeUTF 호출 전 까지 block;
       //    writeUTF 호출 되면 그 때 부터 read 하기 시작
    }catch (IOException e) {   
       e.printStackTrace();
       }
    }
  }
}

 

 

Server2 , Sender와 Receiver를 활용한 클래스

 

public class Server2 {
   public static void main(String[] args) throws IOException {
    
       ServerSocket socket = new ServerSocket(7777);
       System.out.println("준비완료");
       
       Socket socket = nserver.accept();
       
       // toString() 오버라이딩 되어 있음
       System.out.println("server의 소켓 : " + socket);
       
       Sender sender = new Sender(socket);
       Reeceiver receiver = new Receiver(socket);
       
       sender.start();
       receiver.start();
       
       //main, sender, receiver 의 스레드가 작동하년 멀티스레드 프로그램

 

 Client2

 

public class Client2 {
  public static void main(String[] args) throws UnknownHostException, IOException {
  Socket socket = new Socket("localhost", 7777);
  
  System.out.println("서버 연결 완료");
  System.out.println("클라이언트 소켓 : + socket);
  
  
  Sender sender = new Sender(socket);
  Receiver receiver = new Receiver(socket);
  
  sender.start();
  receiver.start();

 

 

'Backend > JAVA' 카테고리의 다른 글

[JAVA] MVC Pattern  (0) 2022.05.09
[JAVA] HashMap  (0) 2022.04.27
[JAVA] chatAt(int i) - '0'  (0) 2022.04.23
[JAVA] 상속(Inheritance)  (0) 2022.04.22
[JAVA] Singleton Pattern  (0) 2022.04.21