본문 바로가기
IT 돌고래/Special JAVA

[Java] TCP 소켓통신 프로그램 만들기(1:1)

by IT돌고래 2020. 3. 9.
반응형

안녕하세요.

IT 돌고래입니다.

자바로 TCP의 소켓 1:1 통신이 되는 자바 프로그램을 만들어 보겠습니다.

 

1. TCP 통신의 이해

2. 소스 분석

 

Main Server

package network;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class MS {

   public static void main(String[] args) {
      // TODO Auto-generated method stub
      try
      {
    	 //1. 서버소켓을 객체로 생성
         ServerSocket s_socket = new ServerSocket(8888);
         
         //2. 서버소켓의 accept함수를 호출해서 결과값 Socket을 Socket에 c_socket변수에 대입
         Socket c_socket = s_socket.accept(); 
         //TCP 통신
         
         
         //3.리시브 스래드 객체 생성
         RT rec_thread = new RT();
         //4.리시브 스래드에 소캣 전달
         rec_thread.setSocket(c_socket);
         //5. 샌드 스래드 생성
         ST send_thread = new ST();
         //6. 샌드 스래드에 소켓 전달
         send_thread.setSocket(c_socket);
         //7. 리시브 스래드 시작
         rec_thread.start();
         //8. 샌드 스래드 시작
         send_thread.start();
      } catch(IOException e){
         //9.입출력의 문제가 생기면 실행
         e.printStackTrace();
      }
   }

}

Main Client

package network;

import java.io.IOException;
import java.net.Socket;
public class MC {

   public static void main(String[] args) {
      // TODO Auto-generated method stub
      
      try {
    	 //1. 소켓생성 특징 서버 ip가 필요, 포트
         Socket c_socket = new Socket("서버IP",8888);
         //2. 리시브 스래드 생성
         RT rec_thread = new RT();
         //3. 리시브 스래드에 소켓 전달
         rec_thread.setSocket(c_socket);
         //4. 샌드 스래드 생성
         CT send_thread = new CT();
         //5. 샌드 스래드에 소켓 전달
         send_thread.setSocket(c_socket);
         //6. 샌드 스래드 시작
         send_thread.start();
         //7. 리시브 스래드 시작
         rec_thread.start();
         
      }catch(IOException e) {
         //입출력 예외 발생시 실행
         e.printStackTrace();
      }

   }

}

Send Thread(Server)

package network;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ST extends Thread {

   private Socket m_Socket; //Socket 타입 변수 m_Socket 선언
      
   public void run() //thread에 있는 thread에서 동작하는 run 함수를 오버라이딩
   {
      super.run(); // 부모 thread에 run 함수 호출
      try {
         BufferedReader tmpbuf = new BufferedReader(new InputStreamReader(System.in));
         //버퍼리더를 이용한 입력 객체 생성
         PrintWriter sendWriter = new PrintWriter(m_Socket.getOutputStream());
         //PrintWriter의 sendWriter로 변수로 선언 후 객체를 생성
         //객체를 생성할때 소켓의 출력 스트림을 인자로 받아서 생성
         String sendString;
         //문자열 변수 sendString 새성
         
         while(true) //무한 반복
         {
            sendString = tmpbuf.readLine();
            //입력을 받아서 문자열 변수 sendString에 대입
            sendWriter.println(sendString);
            //PrintWriter의 println함수에 문자열 변수 sendString을 대입
            sendWriter.flush();
            //PrintWriter의 flush 함수 호출
            // 문자열을 입력 받아서 PrintWriter의 객체에 입력 받은 문자열을 받고
            // PrintWriter의 flush 함수이 호출 되면 문자열 데이터를 전송하게 됩니다.
         }
      }catch(IOException e) {
         //입출력 예외처리 발생시 실행
         e.printStackTrace();
      }
   }
   
   //메인문에서 소켓 객체 받아서 내 변수에 대입
   public void setSocket(Socket _socket)
   {
	   //m_Socket에 main에서 만든 소켓 대입
      m_Socket = _socket;
   }
}

Send Thread(Client)

package network;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class CT extends Thread{
	private Socket m_Socket;
private Socket m_Socket; //Socket 타입 변수 m_Socket 선언
      
   public void run() //thread에 있는 thread에서 동작하는 run 함수를 오버라이딩
   {
      super.run(); // 부모 thread에 run 함수 호출
      try {
         BufferedReader tmpbuf = new BufferedReader(new InputStreamReader(System.in));
         //버퍼리더를 이용한 입력 객체 생성
         PrintWriter sendWriter = new PrintWriter(m_Socket.getOutputStream());
         //PrintWriter의 sendWriter로 변수로 선언 후 객체를 생성
         //객체를 생성할때 소켓의 출력 스트림을 인자로 받아서 생성
         String sendString;
         //문자열 변수 sendString 새성
         
         while(true) //무한 반복
         {
            sendString = tmpbuf.readLine();
            //입력을 받아서 문자열 변수 sendString에 대입
	    if(sendString.equals("quit")) //문자열 변수 sendString의 값이 "quit"면 실행
	    {
		break; // 반복문 종료
	    }
            else // 위에 조건이 아니면
	    {
	         sendWriter.println(sendString);
                 //PrintWriter의 println함수에 문자열 변수 sendString을 대입
                 sendWriter.flush();
                 //PrintWriter의 flush 함수 호출
                 // 문자열을 입력 받아서 PrintWriter의 객체에 입력 받은 문자열을 받고
                 // PrintWriter의 flush 함수이 호출 되면 문자열 데이터를 전송하게 됩니다.
	     }
	  }
	}catch(IOException e) {
            //입출력이 예외처리 발생시 실행
		e.printStackTrace();
	}
    }

   //메인문에서 소켓 객체 받아서 내 변수에 대입
   public void setSocket(Socket _socket)
   {
	   //m_Socket에 main에서 만든 소켓 대입
      m_Socket = _socket;
   }
}

Receive Thread

package network;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class RT extends Thread{
   //소캣 변수 생성
   private Socket  m_Socket;
   // Thread 클래스 run 함수 오버라이딩
   public void run() {
      //1. 부모 쓰래드 run 시작
      super.run();
      
      try {
    	 //2. 버퍼리더 생성 -> m_Socket.getInputStream()(소캣을 이용한 버퍼리더 생성)
         BufferedReader tmpbuf = new BufferedReader(new InputStreamReader(m_Socket.getInputStream()));
         
         //문자열 변수 선언
         String receiveString;
         
         //무한반복
         while(true)
         {
        	 
        	 
        	//문자열 변수  receiveString <- 버퍼리더 리드라인 한줄씩 저장
            receiveString = tmpbuf.readLine();
            
            //만약에 receiveString 널이면 실행
            if(receiveString ==null)
            {
               System.out.println("상대방 연결이 끊겼습니다");
               //출력
               break;
               //반복탈출
            }
            else
            {
                // receiveString을 출력
            	System.out.println("상대방 :"+receiveString);
            }
         }
         //반복문이 끝나면 버퍼리더 종료
         tmpbuf.close();
      }catch(IOException e)
      {
    	 //입출력 예외처리 발생시 실행
         e.printStackTrace();
      }
   }
   //메인문에서 소켓 객체 받아서 내 변수에 대입
   public void setSocket(Socket _socket)
   {
	   //m_Socket에 main에서 만든 소켓 대입
      m_Socket = _socket;
   }
   

}

 

위에 소스를 보면 서버와 클라이언트로 구성됩니다. 그리고 Send와 Receive를 하는 클래스를 만들어서 서버에 데이터를 보내고 받고 클라이언트도 데이터를 보내고 받을 수가 있게 구현됐습니다.

 

Receive는 쓰레드를 필수적으로 사용을 해야합니다. 왜냐하면 언제 데이터를 보낼지 수신입장에서는 알수가 없기 때문입니다.

Send는 쓰레드를 사용하지 않아도 무방합니다. 왜냐하면 보내는 것은 서버나 클라이언트가 직접 원할 때 보내기 때문입니다.

 

※ 긴 글을 읽어 주셔서 감사합니다. 틈틈이 Special Java를 계속 진행해 나가겠습니다.

반응형

댓글