내가 보려고 정리하는/JAVA

Network Test - TCP / UDP - TCP써보자!

보동이용용 2023. 1. 24. 16:54
반응형

소캣을 이용한 통신 프로그래밍을 소켓 프로그래밍이라 한다.

프로세스간의 통신에 사용되는 양쪽 끝단을 소켓이라 한다.

두종류가 있다.

  TCP UDP
연결방식 연결기반(연결 후 통신)
1:1 통신방식(서버:클라이언트)
비연결기반(소포처럼 그냥 보내놓음)
상대방 없이도 연결 가능
특징 ▶데이터의 경계 구분안함(byte-stream)
▶신뢰성 있는 데이터 전송
▶전송 순서가 보장됨
▶수신여부 확인함
   (데이터가 손실되면 재전송)
▶패킷을 관리할 필요가 없음
▶신뢰성 검증하느라 UDP보다 느림
▶데이터의 경계 구분함(datagram)
▶신뢰성 없는 데이터 전송
▶전송 순서 바뀔 수 있음
▶수신여부 확인안함
   (데이터가 손실되어도 알 수 없음)
▶패킷을 관리해주어야함
▶TCP보다 전송속도가 빠름
관련
클래스
▶Socket
▶ServerSocket
▶DatagramSocket
▶DatagramPacket

 


TCP먼저 해보자

 

< 1 > TcpServer를 생성한다.

package kr.or.ddit.basic.tcp;

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

public class TcpServer01 {

	public static void main(String[] args) throws IOException {
		// TCP소켓 통신을 하기 위해 ServerSoket객체를 생성한다. 
		//(사용할 포트번호를 지정해서 생성한다.)
		ServerSocket server = new ServerSocket(7777);
		
		System.out.println("서버가 접속을 기다립니다...");
		
		// accept()메서드
		//  ==> 클라이언트의 연결 요청이 올 때까지 계속 기다린다.
		//	==> 연결 요청이 오면 새로운  Socket객체를 생성해서 클라이언트의 Socket과 연결한다.
		Socket socket = server.accept();
		
		// accept()메서드 이후의 코드는 클라이언트와 연결되어야만 실행되는 코드들이다...  ////연결된 후의 실제 작업은 여기부터
		System.out.println("클라이언트와 연결되어있습니다...");
		System.out.println();
		
		System.out.println("접속한 상대방의 정보 확인...");
		System.out.println("IP주소 : " + socket.getInetAddress().getHostAddress());
		System.out.println("Port번호: " + socket.getPort()); ///임의로 사용안하고 있는 포트번호 서버가 선택하여 연결한다.
		System.out.println();
		
		System.out.println("상대방과 연결된 내 컴의 정보 학인...");
		System.out.println("IP주소 : " + socket.getLocalAddress());
		System.out.println("Port번호: " + socket.getLocalPort());
		System.out.println();
		
		// 클라이언트에게 메시지 보내기 
		// ==> Socket객체의 getOutputStream()메서드를 이용해서 OutputStream객체를 구해서 전송한다.
		OutputStream out = socket.getOutputStream();
		DataOutputStream dout = new DataOutputStream(out); ///자바가 사용하는 자료형 단위로 작성
		
		dout.writeUTF("환영합니다... 어서오세요...");
		System.out.println("메시지를 보냈습니다...");
		
		// 사용했던 소켓과 스트링 닫기
		dout.close();
		socket.close();
		server.close();
		
		

	}

}

1. TCP소켓 통신을 하기 위해 ServerSoket객체를 생성한다. 

     ==>ServerSocket server = new ServerSocket(7777);

 

2.  accept()메서드를 이용하여 Client가 접속하길 기다린다. 

 

-------------  접속이 확인 되면 다음 단계로 넘어간다.  -------------

-------------  이후 TcpClient에서 연결을 시도할 것이다.  -------------

 

3. 접속이 확인되면 정보를 확인하고

 

4. getOutputStream()메서드를 이용해서 OutputStream객체를 구해서 전송한다.

OutputStream out = socket.getOutputStream();
DataOutputStream dout = new DataOutputStream(out); 

dout.writeUTF("환영합니다... 어서오세요...");
System.out.println("메시지를 보냈습니다...");

 

5. 사용한 소켓과 스트링은 닫아준다. close();

dout.close();
socket.close();
server.close();

<2 > TcpClient를 생성한다.

package kr.or.ddit.basic.tcp;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class TcpClient01 {

	public static void main(String[] args) throws UnknownHostException, IOException {
		
		System.out.println("서버에 연결 중입니다...");
		
		// 연결할 서버의 IP주소와 Port번호를 지정하여 Socet객체를 생성한다.
		// Soket객체는 생성이 완료되면 서버로 연결 요청을 보낸다.
//		Socket socket = new Socket("192.168.36.25", 7777);
		Socket socket = new Socket("localhost", 7777);
		
		// 이 부분은 서버와 연결이 완료되어야만 실행되는 부분입니다...
		System.out.println("서버와 연결이 완료되었습니다...");
		System.out.println();
		
		// 서버가 보낸 메시지를 받아서  화면에 출력하기
		
		// Socket객체의 getInputStream()메서드를 이용해서 InputStream객체를 구한다.
		InputStream in = socket.getInputStream();
		DataInputStream din = new DataInputStream(in);
		
		// 서버가 보낸 메시지를 받아서 출력하기
		System.out.println("서버가 보낸 메시지 : " + din.readUTF());
		System.out.println();
		
		System.out.println("연결을 종료합니다...");
		
		// Socket과 스트림 닫기
		din.close();
		socket.close();
		

	}

}

1. 소켓 객체를 생성한다.(연결할 서버의ip주소와 port번호를 지정하여)

Socket socket = new Socket("localhost", 7777);

 

2. 연결이 완료되면 다음 과정을 실행한다.

 

 

3. 서버가 보낸 메시지를 받아서 출력해보자.

3-1. 메세지를 받아서 
         InputStream in = socket.getInputStream();
3-2. 자바에서 사용하는 자료형으로 받고
         DataInputStream din = new DataInputStream(in);

 

4. 출력한다.

System.out.println("서버가 보낸 메시지 : " + din.readUTF());

 

5. 사용한 소켓과 스트림을 닫아준다.

din.close();
socket.close();

 

패키지가 저장된 파일에서 BIN파일 선택,

주소창에서 CMD검색하고 자바에서부터 패키지 클래스 이름 모두 적은 후 실행

하나는 server, 하나는 client이다.

server와 client

 


[  그런데, 이렇게 하면 서버는 보내기만, 클라이언트는 받기만 한다.  ]

=>  [  쓰레드로 받기, 보내기 동시에 해볼 수 있다. ]

 

** 쓰레드는 실행하면 run()메서드가 실행된다.

 

<1> sender를 생성한다. : 메시지를 보내는 역할을 하는 쓰레드

package kr.or.ddit.basic.tcp;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;

// 이 클래스는 소켓을 통해서 데이터(메시지)를 보내는 역할만 하는 쓰레드이다.
public class Sender extends Thread{
	private Socket socket;
	private DataOutputStream dout;
	
	private String name;
	private Scanner scan;
	
	// 생성자
	public Sender(Socket socket) {
		this.socket = socket;
		scan = new Scanner(System.in);
		
		System.out.println("이름 입력 : ");
		name = scan.nextLine();
		
		try {
			dout = new DataOutputStream(this.socket.getOutputStream());
		} catch (IOException e) {
			// TODO: handle exception
		}
	}
	
	@Override
	public void run() {
		while(dout!=null) {
			try {
				dout.writeUTF(name + " : " + scan.nextLine() );
			} catch (Exception e) {
				// TODO: handle exception
			}
		}

	}
	
	
	
}

 

1. 사용할 변수들 선언

2. 생성자에 이름 입력받은 후 DataOutputStream을 생성한다.

3. run()메서드에서 보낼 데이터가 있다면 dout.을 실행하도록 한다.

 

<2> Receiver를 생성한다. : 메시지를 받는 역할을 하는 쓰레드

package kr.or.ddit.basic.tcp;

import java.io.DataInputStream;
import java.net.Socket;

// 이 클래스는 소켓을 통해서 데이터(메시지)를 받아서 화면에 출력하는 역할만 하는 쓰레드
public class Receiver extends Thread {
	private Socket socket;
	private DataInputStream din;
	
	// 생성자
	public Receiver(Socket socket) {
		this.socket = socket;
		try {
			din = new DataInputStream(this.socket.getInputStream());
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
	
	@Override
	public void run() {
		while(din != null) {
			try {
				System.out.println(din.readUTF());
			} catch (Exception e) {
				// TODO: handle exception
			}
			
		}
	}
}

1. 사용할 변수 선언하고2. 생성자에 소켓과 DataInputStream 생성하고3. run()메서드에서 din에 데이터가 있으면 실행한다.

 

<3> 똑같이 TcpServer를 만든다.  => 메시지를 주고 받는 것은 sender와 receiver를 생성하여 실행한다.

package kr.or.ddit.basic.tcp;

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

public class TcpServer02 {

	public static void main(String[] args) {
		try {
			// ServerSocket객체를 만들고 클라이언트의 접속을 기다리다 클라이언트의 접속 요청이 오면
			// 접속된 Socket객체를 구해서 메시지를 받는 쓰레드와 메시지를 보내는 쓰레드객체를 생성할 때
			// 이 Socket을 넣어준다.
			ServerSocket server = new ServerSocket(7777);
			System.out.println("서버가 준비 중입니다...");
			
			Socket socket = server.accept();
			
			Sender sender = new Sender(socket);
			Receiver receiver = new Receiver(socket);
			
			sender.start();
			receiver.start();
			
		} catch (IOException e) {
			// TODO: handle exception
		}
		

	}

}

 

<43> 똑같이 TcpClient를 만든다.  => 메시지를 주고 받는 것은 sender와 receiver를 생성하여 실행한다.

package kr.or.ddit.basic.tcp;

import java.net.Socket;

public class TcpClient02 {

	public static void main(String[] args) {
		try {
			Socket socket = new Socket("192.168.36.51", 7777);
			System.out.println("서버에 연결되었습니다...");
			
			Sender sender = new Sender(socket);
			Receiver receiver = new Receiver(socket);
			
			sender.start();
			receiver.start();
			
		} catch (Exception e) {
			// TODO: handle exception
		}

	}

}

 

쓰레드를 이용하여 메시지 주고 받기

소켓에 사용된 ip주소를 이용하여 다른 사람도 접속할 수 있다.

한명은 서버 한명은 클라이언트가 되는 것이다.

 

 

 

반응형