Network Test - TCP / UDP - TCP써보자!
소캣을 이용한 통신 프로그래밍을 소켓 프로그래밍이라 한다.
프로세스간의 통신에 사용되는 양쪽 끝단을 소켓이라 한다.
두종류가 있다.
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이다.
[ 그런데, 이렇게 하면 서버는 보내기만, 클라이언트는 받기만 한다. ]
=> [ 쓰레드로 받기, 보내기 동시에 해볼 수 있다. ]
** 쓰레드는 실행하면 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주소를 이용하여 다른 사람도 접속할 수 있다.
한명은 서버 한명은 클라이언트가 되는 것이다.