네트워크
소켓 프로그래밍(TCP/IP socket)[JAVA]
솔트리
2022. 3. 31. 20:54
TCP UDP 연결형 비연결형 신뢰성 비신뢰성
Q) TCP 는 왜 신뢰성일까..?
A) 패킷 유실시에 다시 재전송을 하기 때문이다.
Q) 소켓 이란..?
A socket is one endpoint of a two-way communication link between two programs running on the network. A socket is bound to a port number so that the TCP layer can identify the application that data is destined to be sent to.
+ endpoint : ip와 port 번호의 조합
:: 소켓은 서로 다른 프로그램(ex> 서버와 클라이언트)의 양방향 커뮤니케이션을 위한 도구. 소켓은 하나의 포트 번호에 종속되어 있다(클라이언트에서 보내는 데이터를 올바른 어플리케이션에 보내기위해)
소켓 API 실행 흐름
- TCP 소켓 생성
- 소켓을 서버 주소에 바인드 한다.
- 서버 소켓이 클라이언트의 접근을 기다린다.
- 클라이언트가 접근하면 server가 accept() 수락함으로써 서버와 클라이언트가 데이터를 주고 받을 준비가 된다.
=>
- create
- connect
- send/recv
- close
를 처리하는 로직이 필요하다.
자바로 소켓 프로그래밍
자바로 소켓 프로그래밍을 해보려면 위의 create, connect, send/recv, close 의 로직을 만들어줄 자바 메소드와 클래스를 알아야한다.
create : java.net.ServerSocket 클래스를 이용해서 소켓을 생성한다.
- ServerSocket(int port) : 주어진 포트를 사용하는 서버 소켓을 생성한다.
connect : java.net.Socket 클래스를 이용해서 서버 주소와 특정 포트에 연결한다.
- Socket(innetAddress address, int port)
- Socket(String host, int port)
send/recv : BufferedReader와 PrintWriter을 이용해서 문자열을 send/recv 한다.
소켓을 이용해서 서버에 특정 영어 문자열을 보내면 대문자는 소문자로, 소문자는 대문자를 클라이언트에 보내는 프로그램을 짜봤다.
소스코드
- TCPServer.java
package socketProgramming;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public final static int SERVER_PORT=9999;
public static void main(String arg[]) throws IOException
{
Socket client_socket = null; //Client와 통신하기 위한 Socket
ServerSocket server_socket = null; //서버 생성을 위한 ServerSocket - 송수신을 위한 소켓을 생성함
BufferedReader in = null; //Client로부터 데이터를 읽어들이기 위한 입력스트림
PrintWriter out = null; //Client로 데이터를 내보내기 위한 출력 스트림
try{
server_socket = new ServerSocket(SERVER_PORT);
}catch(IOException e)
{
e.printStackTrace();
}
try {
System.out.println("[[[[SERVER]]]]");
System.out.println("연결을 기다리는 중 . . .");
// accept 메소드 : 클라이언트가 들어오는 것을 대기하는 역할
// 클라이언트가 해당 포트로 연결을 시도한다면, accept 메소드는 대기를 풀고, 클라이언트와 연결시키는
// socket 클래스를 생성(client_socket)하여 반환하게 된다.
// client_socket : 클라이언트랑 1:1 연결된 소켓 - client_socket으로 클라이언트와 통신한다.
client_socket = server_socket.accept();
// 소켓으로부터 데이터 읽어옴
in = new BufferedReader(new InputStreamReader(client_socket.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(client_socket.getOutputStream())); //출력스트림 생성
while(true) {
String str = null;
str = in.readLine(); //Client로부터 데이터를 읽어옴
System.out.println("Client로 부터 온 메세지 : " + str);
if(str.equalsIgnoreCase("quit")) { // 클라이언트가 quit을 입력하면 종료
System.out.println("통신 종료 ===========");
break;
}
StringBuilder res = new StringBuilder();
for(int i = 0; i<str.length();i++) {
if(str.charAt(i)<'a') { // 대문자라면 소문자로 바꿔줌 + 32
res.append((char)(str.charAt(i)+32));
}else {
res.append((char)(str.charAt(i)-32));
}
}
out.println(res.toString());
// 버퍼 비움
out.flush();
}
}catch(IOException e){
e.printStackTrace();
}finally {
// 자원반납
if(in!=null) in.close();
if(out!=null) out.close();
if(client_socket!=null) client_socket.close();
if(server_socket!=null) server_socket.close();
}
}
}
- TCPClient.java
package socketProgramming;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
public class TCPClient{
public final static int SERVER_PORT=9999;
public static void main(String[] arg) throws IOException
{
Socket socket = null; //Server와 통신하기 위한 Socket
BufferedReader in = null; //Server로부터 데이터를 읽어들이기 위한 입력스트림
BufferedReader in2 = null; //키보드로부터 읽어들이기 위한 입력스트림
PrintWriter out = null; //서버로 내보내기 위한 출력 스트림
InetAddress ia = null;
try {
ia = InetAddress.getByName("127.0.0.1"); //서버로 접속 ( local 이라서 127.0.0.1)
socket = new Socket(ia, SERVER_PORT);
System.out.println("[[[[CLIENT]]]]");
System.out.println("연결 성공");
System.out.println(socket.toString()); // 소켓 정보 출력
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
in2 = new BufferedReader(new InputStreamReader(System.in));
out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
while(true) {
System.out.print("서버로 보낼 메세지 : ");
String data = in2.readLine(); //키보드로부터 입력
out.println(data); //서버로 데이터 전송
out.flush(); // 버퍼 비움
if(data.equalsIgnoreCase("quit")){
System.out.println("통신 종료 ===========");
break;
}
String str2 = in.readLine(); //서버로부터 되돌아오는 데이터 읽어들임
System.out.println("서버로부터 되돌아온 메세지(lowerCase<->upperCase) : " + str2);
}
}catch(IOException e) {
e.printStackTrace();
}finally {
// 자원반납
if(in!=null) in.close();
if(in2!=null) in2.close();
if(out!=null) out.close();
if(socket!=null) socket.close();
return;
}
}
}
결과
참조: https://reakwon.tistory.com/168
https://lktprogrammer.tistory.com/62