프로그램이 네트워크에서 데이터를 송수신할 수 있도록, "네트워크 환경에 연결할 수 있게 만들어진 연결부"를 "네트워크 소켓(Socket)" 이라고 합니다.
TCP상에서 동작하는 TCP 소켓
UDP에서 동작하는 UDP 소켓
소켓은 프로토콜, IP주소, port번호가 있어야 정의됩니다.
TCP/UDP 구조 위에서 동작하므로 Server - Client 통신 구조를 가지고 있습니다.
통신 연결 요청을 보내는지 받는지에 따라 클라이언트 소켓 (Client Socket) , 서버소켓(Server Socket)으로 나뉩니다.
데이터를 보내는 쪽이 Client, 받는 쪽이 Server 입니다. 이후에는 서로가 데이터를 송수신할 수 있습니다.
한 쪽에서 데이터를 보내고 반대편에서 수신한 뒤 끊어지는 것이 아니라 양 쪽에서 실시간으로 데이터를 송수신 할 수 있기 때문에 실시간 스트리밍이나 채팅에서 주로 사용됩니다.
✔️ 서버와 클라이언트가 직접 데이터를 송수신하는 것이 아니라 서버에서 accept단계에서 만들어지는 소켓을 이용해 클라이언트와 송수신을 한다.
⦁ TCP를 사용하므로 연결 지향형 소켓
⦁ 신뢰성 보장
⦁ 데이터가 순서대로 송수신
⦁ 점대점 연결
connect() 과정이 따로 없어 소켓을 생성한 후 바로 데이터 전송을 하기 때문에 주로 일대 다 통신에 쓰입니다.
⦁ UDP를 사용하므로 비 연결형 소켓
⦁ 신뢰성을 보장할 수 없음
⦁ 데이터가 순서대로 송수신될 지를 보장할 수 없음
⦁ 점대점 연결뿐만 아니라 일대다도 가능
package socketecho;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class socketServer {
private ServerSocket serverSocket;
// 서버 소켓
private BufferedReader br;
// 클라이언트로부터 전달받은 메시지를 읽어들일 버퍼 메모리
private PrintWriter pw;
// 클라이언트로 메시지를 보냄
private Socket clientSocket;
// 클라이언트 소켓
public static void main(String[] args) {
new socketServer();
}
public socketServer() {
init();
}
public void init() {
try {
serverSocket = new ServerSocket(8981);
// 현재 아이피로 8981포트를 사용하여 서버 오픈
System.out.println("Server is ready");
System.out.println("connect clinet...");
clientSocket = serverSocket.accept();
System.out.println("Client has accepted");
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// 클라이언트로 부터 데이터를 읽어올 준비
pw = new PrintWriter(clientSocket.getOutputStream());
// 클라이언트로 부터 데이터를 보낼 준비
String readData = "";
// 클라이언트로 부터 읽어온 데이터를 저장할 공간
while (!(readData = br.readLine()).equals(null)) {
System.out.println("from Client>" + readData);
pw.println(readData);
// 읽은 메시지를 그대로 클라이언트에 다시 보냄
pw.flush();
// 프린트 라이터 메모리를 초기화 시켜야 데이터가 보내짐
}
clientSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 서버의 포트번호 정함
- 서버용 소켓 객체 생성
- 클라이언트 쪽에서 접속 요청이 오길 기다림
- 접속 요청이 오면 요청 수락 후 해당 클라이언트에 대한 소켓 객체 생성
- 연결된 클라이언트와 입출력 스트림 생성
- 보조 스트림을 통해 성능 개선
- 스트림을 통해 읽고 쓰기
- 통신 종료
package socketecho;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class socketClient {
private Socket clientSocket;
// 클라이언트 소켓
private BufferedReader br;
// 클라이언트로부터 전달받은 메시지를 읽어들일 버퍼 메모리
private PrintWriter pw;
// 클라이언트로 메시지를 보냄
private Scanner sc;
// 데이터 입력
public static void main(String[] args) {
new socketClient();
}
public socketClient() {
init();
}
public void init() {
try {
clientSocket = new Socket("localhost", 8981);
System.out.println("Server Connect");
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// 서버로 부터 데이터를 받아올 준비
pw = new PrintWriter(clientSocket.getOutputStream());
// 서버로 데이터를 보낼 준비
sc = new Scanner(System.in);
//입력한 데이터를 읽을 준비
//System.out.println("");
String inputData = "";
//입력한 데이터를 저장할 공간
while(!inputData.equals("exit")) {
System.out.print("to Server: ");
pw.println(sc.next());
//보낼 내용을 읽어와서 서버로 보낸다
pw.flush();
//프린터 라이터 메모리를 초기화 시켜서 내부에 있던 데이터를 서버로 전송한다
System.out.println("from Server: " + br.readLine());
//서버에서 받은 데이터를 표기한다.
}
clientSocket.close();
//연결 종료하면 소켓을 닫는다.
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 서버의 IP주소와 서버가 정한 포트번호를 매개변수로 하여 클라이언트용 소켓 객체 생성
- 서버와의 입출력 스트림 오픈
- 보조 스트림을 통해 성능 개선
- 스트림을 통해 읽고 쓰기
- 통신 종료
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.ServerSocket;
import java.net.Socket;
public class EchoServer {
public static void main(String[] args) throws IOException {
try (ServerSocket serverSocket = new ServerSocket(9090)) {
System.out.println("Listening...");
while (true) {
Socket socket = serverSocket.accept();
Thread thread = new Thread(new EchoThread(socket));
thread.start();
}
}
}
}
class EchoThread implements Runnable {
private Socket socket;
EchoThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (InputStream io = socket.getInputStream(); OutputStream os = socket.getOutputStream()) {
BufferedReader reader = new BufferedReader(new InputStreamReader(io, "UTF-8"));
PrintWriter pw = new PrintWriter(os, true);
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
System.out.println(line);
if(line.equals("exit")) {
System.out.println("client disconnect");
break;
}
pw.println(line);
pw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.net.*;
import java.io.*;
public class UDPEchoServer {
public UDPEchoServer(int port) {
try {
DatagramSocket ds = new DatagramSocket(port);
while (true) {
byte buffer[] = new byte[512];
DatagramPacket dp = new DatagramPacket(buffer,buffer.length);
System.out.println("ready");
ds.receive(dp);
String str = new String(dp.getData());
System.out.println("수신된 데이터 : " + str);
InetAddress ia = dp.getAddress();
port = dp.getPort();
System.out.println("client ip : " + ia + " , client port : " + port);
dp = new DatagramPacket(dp.getData(),dp.getData().length, ia,port);
ds.send(dp);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
new UDPEchoServer(3000);
}
}
import java.net.*;
import java.io.*;
public class UDPEchoClient{
private String str;
private BufferedReader file;
private static int SERVERPORT=3000;
public UDPEchoClient(String ip,int port){
try{
InetAddress ia = InetAddress.getByName(ip);
DatagramSocket ds = new DatagramSocket(port);
System.out.print("message : ");
file = new BufferedReader(new InputStreamReader(System.in));
str = file.readLine();
byte buffer[] = str.getBytes();
DatagramPacket dp = new DatagramPacket(
buffer,buffer.length,ia,SERVERPORT);
ds.send(dp);
buffer = new byte[512];
dp = new DatagramPacket(buffer,buffer.length);
ds.receive(dp);
System.out.println("server ip : "+dp.getAddress() + " , server port : "+dp.getPort());
System.out.println("수신된 데이터 : "+ new String(dp.getData()).trim());
}catch(IOException ioe){
ioe.printStackTrace();
}
}
public static void main(String[] args){
new UDPEchoClient("localhost",2000);
}
};