[포스코DX|Java|2주] 8일차 수업
포스코DX X 비트교육센터 6기 - 소켓통신
TCP 소켓 프로그래밍
- 스트림 통신 프로토콜
- client와 server사이에서, 보낸 만큼 모두 받을 수는 없다. stream 통신이기 때문이고, 경계가 없다라는 말을 한다. 100byte 보내도 2번에 걸쳐 50byte 씩읽을 수 있다.
- 그러기에, 응용 프로토콜(보조 스트림)을 이용하여
경계를 만들어주어야한다.(ex. send된 것에 개행이 있을 때 까지 recieve하게 하여 server가 받게한다.)
- 소켓 주소를 binding한다.
- client가 소켓을 만들어서 connect를 호출한다. (패킷이 하나 날아간다. 데이터가 없는. 연결 요청 패킷.)
- accept() 단계에서 연결이 됨을 확인함. 이 과정이 blocking이 된다고 말한다.
- write / read가 진행된다.
- 끝나면 close한다.
코딩해보기
package test;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
public class TCPServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
//1. Server Socket 생성
serverSocket = new ServerSocket();
//2. 바인딩(Binding)
// Socket에 InetSocketAddress(IPAddresss + port)를 바인딩 한다.
// IPAddress: 0.0.0.0: 특정 호스트 IP에 바인딩 하지 않는다.
// IPAddress : 내가 접속할 IP주소 0.0.0.0 - 특정 호스트 IP에 바인딩하지 않는다, 아무데서나 접근 가능
serverSocket.bind(new InetSocketAddress("0.0.0.0", 5000), 10);
//3. accept
Socket socket = serverSocket.accept(); // blocking
try {
InetSocketAddress remoteInetSocketAddress = (InetSocketAddress)socket.getRemoteSocketAddress();
String remoteHostAddress = remoteInetSocketAddress.getAddress().getHostAddress();
int remotePort = remoteInetSocketAddress.getPort();
System.out.println("[server] connected by client[" + remoteHostAddress + ":" + remotePort + "]");
//4. IO Stream 받아오기
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream();
while(true) {
//5. 데이터읽기
byte[] buffer = new byte[256];
int readByteCount = is.read(buffer); // blocking
if(readByteCount == -1) {
// 클라이언트가 정상적으로 종료(close() 호출)
System.out.println("[server] closed by client");
break;
}
String data = new String(buffer, 0, readByteCount, "utf-8");
System.out.println("[server] received:" + data);
//6. 데이터 쓰기
os.write(data.getBytes("utf-8"));
}
} catch(SocketException e) {
System.out.println("[server] suddenly closed by client");
} catch (IOException e) {
System.out.println("[server] error:" + e);
} finally {
try {
if(socket != null && !socket.isClosed()) {
socket.close();
}
} catch(IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
System.out.println("[server] error:" + e);
} finally {
try {
if(serverSocket != null && !serverSocket.isClosed()) {
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- 텔넷 다운로드
- 텔넷 사용 이유?
- telnet은 통신 인터페이스를 제공하는 프로토콜입니다. 연결을 시도하는 클라이언트 컴퓨터가 가상의 연결 통로를 통해 원격으로 서버 컴퓨터(호스트)에 접속할 수 있게 해 줍니다.
- 현재 telnet은 클라이언트가 서버의 특정 포트로 잘 연결되는지 확인하기 위한 도구로 가장 많이 활용되지 않을까 싶습니다. 통신 가능 여부를 확인하고 연결이 불가하면 방화벽 오픈 작업을 하는 식입니다.
- 연결 완료
- GET / HTTP/1.1
- 텔넷에서 자동으로 개행을 넣어줌.
C:\Users\pc\Desktop\poscodx2023\eclipse\java-study\network\target\classes>java test.TCPServer
C:\Users\pc\Desktop\poscodx2023\eclipse\java-study\network\target\classes>java echo.EchoServer
Thread
package thread;
public class threadEx01 {
public static void main(String[] args) {
//for(int i = 0 ; i <10; i++) {
// System.out.print(i);
//}
//Thread를 쓰면, 자리 선점하는데 시간이 걸려서 밀린다.
//출력 결과 : abc0123456789defghijklmnopqrstuvwxyz
new DigitalThread().start();
for(char c= 'a'; c<= 'z'; c++) {
System.out.print(c);
try {
//sleep을 통해 이 두 가지 for문을 섞어줌.
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package thread;
public class DigitalThread extends Thread {
@Override
public void run() {
for(int i = 0 ; i <10; i++) {
System.out.print(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
http 는
문서를 공유하기 위함이다.
연결을 계속 유지할 필요가 없다.
왜냐하면 문서를 읽는 시간이 있기 때문에, 요청이 계속 하지 않고
연결을 계속 남겨두면 낭비다.
효율적으로하기 위해 http는 문서를 받고 연결을 끊어둔다.