AWS BACK DAY 26. 소켓 통신

이강용·2023년 2월 7일

Java 기초

목록 보기
20/26

📌Socket(소켓) 통신

  • 소켓(Socket)은 TCP/IP 기반 네트워크 통신에서 데이터 송수신의 접점을 의미, 서버 - 클라이언트 간 데이터를 주고받는 양방향 연결 지향성 통신 , 소켓 통신은 지속적으로 연결을 유지하면서 실시간으로 데이터를 주고받아야 하는 경우에 사용

  • 소켓은 클라이언트 소켓서버 소켓으로 구분되며, 소켓간 통신을 위해서는 네트워크상에서 클라이언트와 서버에 해당되는 컴퓨터를 식별하기 위한 IP주소와 해당 컴퓨터내에서 현재 통신에 사용되는 응용프로그램을 식별하기 위한 포트번호가 사용

    http 프로토콜
    A : server 야 이거 B 한테 줘
    B : server 야 뭐 온거 없어?
    server : A 가 너 주래

📌서버(Server)와 클라이언트(Client)

  • 소켓통신에서는 서버와 클라이언트가 존재하며, 서버(Server)는 데이터를 제공하는 쪽을 말하며, 클라이언트(Client)는 데이터를 요청하여 제공받는 쪽을 말함

📌서버(Server) 소켓 구현

  1. 서버 소켓 생성
ServerSocket serverSocket = new ServerSocket(@@@@) //@@@@ : 포트번호
  1. 클라이언트 접속 대기
Socket socket = serverSocket.accept();
  1. 데이터 송수신을 위한 I/O 스트림 생성
InputStream ins = socket.getInputStream();
OutputStream outs = socket.getOutputStream();
  1. INPUT 스트림을 통한 데이터 수신 (Client → Server)
byte[] inputData = new byte[100];
int length = ins.read(inputData);
String inputMessage = new String(inputData,0,length);
  1. OUTPUT 스트림을 통한 데이터 송신 (Server → Client)
String outputMessage = "전송할 메시지 입력: ";
outs.write(outputMessage.getBytes());
out.flush();
  1. 통신 종료
socket.close();
serverSocket.close();

📌클라이언트(Client) 소켓 구현

  1. 클라이언트 소켓 생성 및 서버접속
Socket socket = new Socket("127.0.0.1",@@@@) // IP주소 및 포트번호
  1. 데이터 송수신을 위한 I/O 스트림 생성
InputStream inC = socket.getInputStream();
OutputStream outC = socket.getOutputStream();
  1. OUTPUT 스트림을 통한 데이터 송신 (Client → Server)
String outputMessage = "전송할 메시지 입력: ";
outs.write(outputMessage.getBytes());
out.flush();
  1. INPUT 스트림을 통한 데이터 수신(Server → Client)
byte[] inputData = new byte[100];
int length = ins.read(inputData);
String inputMessage = new String(inputData,0,length);
  1. 통신 종료
socket.close();

📌Buffered(Reader, Writer) & PrintWriter, PrintStream

  • 데이터 전송의 기본단위는 바이트(Byte)로 문자의 경우 데이터 전송시 문자를 바이트로, 수신시 바이트로 문자로 변환이 필요, 앞에서는 String Class의 생성자와 getBytes method를 사용

  • JAVA에는 이 변환을 편리하게 해주는 클래스인 InputStramReaderOutputStreamWriter가 있으며 charset을 지정하여 사용할 수 있음, 또한 효율적인 데이터 입출력을 위해 바로 전달하지 않고 중간에 버퍼를 사용하는데 이때 사용하는 클래스가 BufferedReaderBufferedWriter

BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
  • 데이터 출력의 경우, 출력 포맷을 편리하게 해주는 PrintWriter, PrintStream 클래스가 있음
PrintWriter pw = new PrintWrier(socket.getOutputStream());
PrintStream ps = new PrintStream(socket.getOutputStream());

Server

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class SocketServer {
	
	public static final int PORT = 9090;
	
	public static void main(String[] args) {
		List<Socket> clients = new ArrayList<>();
		
		try {
			ServerSocket serverSocket = new ServerSocket(PORT);
			while(true) {
				System.out.println("클라이언트의 접속을 기다리는 중입니다.");
				Socket socket = serverSocket.accept();
				clients.add(socket);
				System.out.println("클라이언트가 연결되었습니다.");
				System.out.println(clients);
				OutputStream outputStream = socket.getOutputStream();
				PrintWriter out = new PrintWriter(outputStream, true);
				out.println("___서버에 접속한 것을 환영합니다.");
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}

Client

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

public class SocketClient {
	
	public static void main(String[] args) {
		try {
			Socket socket = new Socket("127.0.0.1", 9090);
			System.out.println("서버에 접속 성공!");
			
			InputStream inputStream = socket.getInputStream();
			InputStreamReader streamReader = new InputStreamReader(inputStream);
			BufferedReader reader = new BufferedReader(streamReader);
			
			System.out.println(reader.readLine());
			
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}

🔥심화) MultiSocket

Server

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

public class Server {

	private static final int PORT = 9090;
	
	public static void main(String[] args) {
		try {
			ServerSocket serverSocket = new ServerSocket(PORT);
			System.out.println("서버를 실행합니다.");
			
			while(true) {
				Socket socket = serverSocket.accept();
				SocketServer socketServer = new SocketServer(socket);
				socketServer.start();
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			System.out.println("서버를 종료합니다.");
		}
	}
	
}

SocketServer

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class SocketServer extends Thread {
	
	public static List<SocketServer> clientList = new ArrayList<>();
	private Socket socket;
	private String name;
	
	public SocketServer(Socket socket) {
		this.socket = socket;
		clientList.add(this);
	}
	
	@Override
	public void run() {
		System.out.println("[연결된 클라이언트 정보]");
		System.out.println("IP: " + socket.getInetAddress());
		
		try {
			InputStream inputStream = socket.getInputStream();
			BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
			
			OutputStream outputStream = socket.getOutputStream();
			PrintWriter writer = new PrintWriter(outputStream, true);
			
			writer.println("서버 접속 성공!");
			writer.println("사용자 이름을 입력하세요!");
			
			String message = null;
			boolean loginFlag = false;
			while((message = reader.readLine()) != null) {
				if(name == null) {
					name = message;
					System.out.println("\n서버에 " + name + "님이 접속하였습니다.");
				}
				
				for(SocketServer s : clientList) {
					try {
						outputStream = s.socket.getOutputStream();
						writer = new PrintWriter(outputStream, true);
						if(!loginFlag) {
							writer.println("\n" + s.name + "님이 접속하였습니다.");
							loginFlag = true;
							continue;
						}
						writer.println("\n" + s.name + ": " + messase);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
			
			
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

Client

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

public class Client {
	
	public static String name;
	
	public static void main(String[] args) {
		try {
			Socket socket = new Socket("127.0.0.1", 9090);
			System.out.println("서버에 접속함?");
			
			ClientRecive clientRecive = new ClientRecive(socket);
			clientRecive.start();
			
			ClientSend clientSend = new ClientSend(socket);
			clientSend.start();
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}

ClientRecive

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

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class ClientRecive extends Thread {

	private final Socket socket;
	
	@Override
	public void run() {
		try {
			InputStream inputStream = socket.getInputStream();
			BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
			
			while(true) {
				System.out.println(reader.readLine());		
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

ClientSend

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

import com.mysql.cj.jdbc.exceptions.MySQLStatementCancelledException;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class ClientSend extends Thread {

	private final Socket socket;
	
	@Override
	public void run() {
		try {
			OutputStream outputStream = socket.getOutputStream();
			PrintWriter writer = new PrintWriter(outputStream, true);
			Scanner scanner = new Scanner(System.in);
			
			while(true) {
				if(Client.name == null) {
					Client.name = scanner.nextLine();
					writer.println(Client.name);
					continue;
				}
				writer.println(scanner.nextLine());
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}

📌Thread

public class LoopThread extends Thread {
	
	private String threadName;
	
	public LoopThread(String threadName) {
		this.threadName = threadName;
	}
	
	
	@Override
	public void run() {
		
		for (int i = 0; i< 10; i++) {
			System.out.println(threadName + ":" + i);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}
	
}
public class ThreadTest {
	
	public static void main(String[] args) {
		
		LoopThread loopThread1 = new LoopThread("김상현");
		LoopThread loopThread2 = new LoopThread("강대협");
		LoopThread loopThread3 = new LoopThread("손지호");
		LoopThread loopThread4 = new LoopThread("김재영");
		
		loopThread1.setPriority(6);
		loopThread4.setPriority(7);
		System.out.println(loopThread1.getPriority());
		System.out.println(loopThread2.getPriority());
		System.out.println(loopThread3.getPriority());
		System.out.println(loopThread4.getPriority());
		
		loopThread1.start();  // start가 호출되면 LoopThread.run()이 실행된다.
		loopThread2.start();
		loopThread3.start();
		loopThread4.start();
		
		/*
		 * Thread 
		 * 숫자가 클 수록 우선순위가 높음
		 * 
		 */
		
	}

}
profile
HW + SW = 1

0개의 댓글