JAVA/네트워크 입출력
[Java] TCP 네트워킹
숭어싸만코
2023. 6. 2. 12:59
TCP 네트워킹
-TCP는 연결형 프로토콜로 상대방이 연결된 상태에서 데이터를 주고 받는다.
-클라이언트가 연결 요청을 하고 서버가 연결을 수락하면 고정회선을 통해 데이터 전달
-java.net 패키지에서 ServerSocket 과 Socket 클래스 제공
- ServerSocket : 클라이언트의 연결을 수락하는 서버쪽 클래스
- Socket : 클라이언트 연결요청과 양쪽 데이터를 주고 받을때 사용 되는 클래스
[서버]
- ServerSocket / Scoket 이용
package study0602.Network;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class ServerExample {
private static ServerSocket serverSocket = null;
public static void main(String[] args) {
// P.831
System.out.println("---------------------------");
System.out.println("서버를 종료하면 q 또는 Q를 입력하고 Enter 키를 입력하세요.");
System.out.println("---------------------------");
// TCP 서버시작
startServer();
// 키보드 입력
Scanner sc = new Scanner(System.in);
while (true) {
String key = sc.nextLine();
if (key.toLowerCase().equals("q")) {
break;
}
}
sc.close();
// TCP서버 종료
stopServer();
}//
private static void startServer() {
// 작업 스레드 정의
Thread thread = new Thread() {
@Override
public void run() {
try {
// ServerSocket 생성 및 Port 바인딩
serverSocket = new ServerSocket(50001);
System.out.println("[서버] 시작됨");
while (true) {
System.out.println("[서버] 연결 요청을 기다림");
// 연결 수락
Socket socket = serverSocket.accept();
// 연결된 클라이언트 정보 얻기
InetSocketAddress isa = (InetSocketAddress) socket.getRemoteSocketAddress();
System.out.println("[서버]" + isa.getHostName() + "연결 요청을 수락함");
// 연결 끊기
socket.close();
System.out.println("[서버]" + isa.getHostName() + "의 연결을 끊음");
}
} catch (IOException e) {
// TODO: handle exception
System.out.println("[서버]" + e.getMessage());
}
}
};
// 스레드 시작
thread.start();
}
private static void stopServer() {
try {
// ServerSocket을 닫고 Port 언바인딩
serverSocket.close();
System.out.println("[서버] 종료됨");
} catch (IOException e1) {
// TODO: handle exception
}
}
}//
[클라이언트]
- Socket 이용
package study0602.Client;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientExample {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
//Socket 생성과 동시에 localhost의 50001 Port로 연결 요청;
Socket socket = new Socket("localhost",50001);
System.out.println("[클라이언트] 연결성공");
//Socket 닫기
socket.close();
System.out.println("[클라이언트] 연결 끊기");
}catch (UnknownHostException e) {
// IP 표기방법이 잘못되었을경우
}
catch (IOException e) {
// 해당 포트의 서버에 연결할 수 없는 경우
}
}//
}//
입출력 스트림으로 데이터 주고받기
- 클라이언트가 연결 요청( connect( ) )을 하고 서버가 연결 수락 ( accept( ) ) 했다면, 양쪽의 Socket객체로부터 각각 입력 스트림 ( InputStream ) 과 출력 스트림 ( OutPutStream ) 을 얻을 수 있다.
- 문자열을 간편하게 주고 받고 싶다면 보조 스트림 DataOutputStream / DataInputStream을 연결해서 사용 하면 된다.
DataOutputStream / DataInputStream 을 이용한 예제
[Server]
package study0602.Network;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class EchoServer {
private static ServerSocket serverSocket = null;
public static void main(String[] args) {
// P.838 입출력 스트림으로 데이터 받기
System.out.println("---------------------------");
System.out.println("서버를 종료하면 q 또는 Q를 입력하고 Enter 키를 입력하세요.");
System.out.println("---------------------------");
//TCP 서버시작
startServer();
//키보드 입력
Scanner sc= new Scanner(System.in);
while (true) {
String key = sc.nextLine();
if(key.toLowerCase().equals("q")) {
break;
}
}
sc.close();
//TCP서버 종료
stopServer();
}//
private static void startServer() {
Scanner sc = new Scanner(System.in);
// 작업 스레드 정의
Thread thread = new Thread(){
@Override
public void run() {
try {
//ServerSocket 생성 및 Port 바인딩
serverSocket = new ServerSocket(50001);
System.out.println("[서버] 시작됨");
while (true) {
System.out.println("[서버] 연결 요청을 기다림");
//연결 수락
Socket socket = serverSocket.accept();
//연결된 클라이언트 정보 얻기
InetSocketAddress isa =
(InetSocketAddress)socket.getRemoteSocketAddress();
System.out.println("[서버]"+ isa.getHostName()+"연결 요청을 수락함");
//-----------------------------------------------------
//==데이터 받기
DataInputStream dis = new DataInputStream(socket.getInputStream());
String message = dis.readUTF();
System.out.println("[서버] 받은 데이터 : " + message);
//데이터 보내기
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
System.out.println("=====클라이언트에게 보낼 메세지 입력=====");
String send =sc.nextLine();
System.out.println("=======================");
dos.writeUTF(send);
dos.flush();
//----------------------------------------------------
//연결 끊기
socket.close();
System.out.println("[서버]"+isa.getHostName()+ "의 연결을 끊음");
}
} catch (IOException e) {
// TODO: handle exception
System.out.println("[서버]"+e.getMessage());
}
}
};
//스레드 시작
thread.start();
}
private static void stopServer() {
try {
//ServerSocket을 닫고 Port 언바인딩
serverSocket.close();
System.out.println("[서버] 종료됨");
} catch (IOException e1) {
// TODO: handle exception
}
}
}//
[Client]
package study0602.Client;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class EchoClient {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
try {
//Socket 생성과 동시에 localhost의 50001 Port로 연결 요청;
Socket socket = new Socket("localhost",50001);
System.out.println("[클라이언트] 연결성공");
//----------------------------------------
System.out.println("======메세지 입력======");
String sendMessage = sc.nextLine();
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF(sendMessage);
dos.flush();
System.out.println("[클라이언트] 데이터 보냄: "+sendMessage);
//데이터 받기
DataInputStream dis=new DataInputStream(socket.getInputStream());
String receiveMessage = dis.readUTF();
System.out.println("[클라이언트] 데이터 받음: " +receiveMessage );
//----------------------------------------
//Socket 닫기
socket.close();
System.out.println("[클라이언트] 연결 끊기");
}catch (UnknownHostException e) {
// IP 표기방법이 잘못되었을경우
}
catch (IOException e) {
// 해당 포트의 서버에 연결할 수 없는 경우
}
}//
}//