일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 디자인패턴
- 자바ORM표준JPA프로그래밍
- Java
- 영속성컨텍스트
- 알고리즘
- 아두이노
- Spring Batch
- Hibernate
- 장애물인식
- DeepLearning
- 딥러닝
- 포인트클라우드
- 자바
- 운영체제
- 네트워크
- 논문리뷰
- MySQL
- Jetson
- 프로그래머스
- 자료구조
- Python
- persistance context
- 논문
- cartograhper
- Database
- 자율주행
- 이펙티브자바
- 파이썬
- JPA
- 배달로봇
- Today
- Total
제리 devlog
[Java] 소켓 통신 (간단한 채팅 프로그램 구현) 본문
Socket이란?
socket은 application layer와 transport layer사이의 인터페이스역할을 담당하며 서로 다른 endpoint간 통신을 위해서 사용된다.
Socket의 동작 과정
서버측 동작 과정
1. 서버는 socket를 만든다.
2. 서버에서 ip주소와 port를 지정하여 소켓에 바인딩한다.
3. 서버는 listen상태가 되어 클라이언트의 요청을 기다린다.
4. 클라이언트의 요청을 받아드리고 데이터 송수신을 위한 소켓을 생성한다.
5. 클라이언트와 데이터를 송/수신한다.
6. 연결을 종료한다.
클라이언트측 동작 과정
1. socket을 만든다.
2. 서버에게 요청을 보내 connection을 맺는다.
3. 서버와 데이터를 송/수신한다.
4. 연결을 종료한다.
Java 프로그램 구현
한가지 유의할 점은 데이터 송수신시 별도의 스레드를 만들어야한다. 데이터 송수신은 blocking방식으로 동작하기때문에 메인스레드로만 구성하면 데이터를 올바르게 수신할 수 없다.
서버
데이터 전송
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
public class SendThead extends Thread{
private final Socket socket;
private Scanner scanner = new Scanner(System.in);
public SendThead(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
DataOutputStream sendWriter = new DataOutputStream(socket.getOutputStream());
String sendString;
while(true){
sendString = scanner.nextLine();
sendWriter.writeUTF(sendString);
sendWriter.flush();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
서버에서 클라이언트로 데이터를 전송하는 스레드이다.
별도의 Thread를 만들기위해 Thread클래스를 상속받아 run()메서드를 구현한다.
socket.getOutputStream()을 사용해서 클라이언트에게 데이터를 전송할 수 있다.
데이터 수신
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
public class ReceiveThread extends Thread {
private final Socket socket;
public ReceiveThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
DataInputStream tmpbuf = new DataInputStream(socket.getInputStream());
String receiveString;
while (true) {
receiveString = tmpbuf.readUTF();
System.out.println("상대방 : " + receiveString);
}
} catch (SocketException e1) {
System.out.println("상대방 연결이 종료되었습니다.");
} catch (IOException e2) {
e2.printStackTrace();
}
}
}
클라이언트에서 온 데이터를 수신하는 스레드이다.
마찬가지로 별도의 Thread를 만들기위해 Thread클래스를 상속받아 run()메서드를 구현한다.
socket.getIntputStream()을 사용해서 클라이언트에게 데이터를 수신할 수 있다.
메인 함수
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketServer {
public static void main(String[] args) throws IOException {
int port = 8888;
ServerSocket socketServer = new ServerSocket(port);
while(true) {
Socket sock = socketServer.accept();
System.out.println("ip : " + sock.getInetAddress() + " 와 연결되었습니다.");
ReceiveThread receiveThread = new ReceiveThread(sock);
receiveThread.start();
SendThead sendThead = new SendThead(sock);
sendThead.start();
}
}
}
서버에서는 port를 지정해서 소켓과 바인딩 시킨다. 이후 클라이언트의 요청을 기다리고 요청이 들어오면 데이터 송수신 스레드를 만들어 통신한다.
클라이언트
클라이언트의 코드는 거의 서버측과 유사하다.
데이터 전송
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
public class SendThread extends Thread{
private final Socket socket;
Scanner scanner = new Scanner(System.in);
public SendThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
DataOutputStream sendWriter = new DataOutputStream(socket.getOutputStream());
String sendString;
while(true){
sendString = scanner.nextLine();
sendWriter.writeUTF(sendString);
sendWriter.flush();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
데이터 수신
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
public class ReceiveThread extends Thread {
private final Socket socket;
private String receiveString;
public ReceiveThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
DataInputStream tmpbuf = new DataInputStream(socket.getInputStream());
while (true) {
receiveString = tmpbuf.readUTF();
if (receiveString == null) {
System.out.println("상대방 연결이 종료되었습니다.");
} else {
System.out.println("상대방 : " + receiveString);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
메인 함수
import java.io.IOException;
import java.net.Socket;
public class SocketClient {
public static void main(String[] args) throws IOException {
Socket sock = new Socket("localhost", 8888);
System.out.println("서버와 접속되었습니다.");
ReceiveThread receiveThread = new ReceiveThread(sock);
receiveThread.start();
SendThread sendThead = new SendThread(sock);
sendThead.start();
}
}
클라이언트에서는 서버의 ip주소와 port를 사용해 connection을 맺는다. 이후 데이터 송수신 스레드가 실행된다.
'Java' 카테고리의 다른 글
[JAVA] Java8부터는 static이 heap영역에 저장된다? (3) | 2021.05.27 |
---|---|
[JAVA] Serial GC, Parallel GC, Parallel Old GC 동작 원리 (0) | 2021.05.27 |
[이펙티브 자바] 맴버 클래스는 되도록 static으로 만들라 (0) | 2021.01.14 |
[이펙티브자바] 인터페이스는 타입을 정의하는 용도로만 사용하라 (0) | 2021.01.11 |
[이펙티브 자바] 추상 클래스보다는 인터페이스를 우선하라 (0) | 2021.01.04 |