forked from kimahhh/be-was
-
Notifications
You must be signed in to change notification settings - Fork 0
Socket
SeoSiun edited this page Jul 17, 2023
·
2 revisions
-
TCP/IP 기반 네트워크 통신에서 데이터 송수신
-
양방향 연결 지향성 통신
- 지속적으로 연결을 유지하면서 실시간으로 데이터를 주고받아야 하는 경우 사용.
-
Process to Process 통신
-
IP와 Port number를 통해 연결
- IP: 통신을 할 컴퓨터(device)를 식별
- Port number: 해당 컴퓨터 내에서 현재 통신에 사용될 응용프로그램(프로세스) 식별
-
소켓의 역할에 따라 클라이언트 소켓과 서버 소켓으로 구분
- 서버: 데이터를 제공하는 쪽
- 클라이언트: 데이터를 요청하여 제공받는 쪽
-
서버
- 서버소켓 생성
- IP, port 바인딩
- 클라이언트 접속 대기
-
클라이언트
- 클라이언트 소켓 생성
- 서버의 IP, port로 통신 시도
- 연결 후 read(), write()로 통신
-
cf) 하나의 서버에 여러 클라이언트가 접속한다면?
-
클라이언트 하나 당 한 개의 Socket(하나의 커넥션)이 생성됨
⇒ Thread를 사용하자!
-
- HTTP
- 클라이언트의 요청이 있을 때 서버가 요청 수행 및 응답을 보내고, 바로 연결 종료
- 클라이언트가 요청을 보낼 때만 서버가 응답하는 단방향 통신 (서버가 클라이언트에 요청을 보낼 수는 없음)
- Socket
- 서버와 클라이언트가 특정 포트를 통해 실시간으로 양방향 통신
- 서버와 클라이언트의 연결이 계속 유지되는 양방향 통신
-
클라이언트 소켓의 연결 요청을 기다리다가(block), 요청이 오면 클라이언트와 통신하기 위한 소켓(Socket 객체)를 생성하여 리턴
- 이때 새로 생성된 소켓은 ServerSocket과 다른 포트를 사용 (랜덤한 포트가 할당됨)
- ServerSocket이 쓰는 포트는 클라이언트 요청 listen을 위한 포트이므로
package java.net; class ServerSocket implements java.io.Closeable { ... /** /* 넘겨받은 포트에 바인딩된 server socket 생성 /* port에 0을 넘기면 포트를 자동으로 할당해줌. /* (getLocalPort()를 통해 할당받은 포트 번호 확인 가능) **/ public ServerSocket(int port) throws IOException { this(port, 50, null); } ... /** /* 소켓에 대한 connection을 listen하고 accept함. /* connection이 생성될 때까지 block됨 /* 실제 통신을 담당할 Socket 인스턴스를 생성해서 리턴 **/ public Socket accept() throws IOException { if (isClosed()) throw new SocketException("Socket is closed"); if (!isBound()) throw new SocketException("Socket is not bound yet"); Socket s = new Socket((SocketImpl) null); implAccept(s); return s; } /** /* (보통 빈) 소켓을 넘겨받아 client에 연결해줌 **/ protected final void implAccept(Socket s) throws IOException { SocketImpl si = null; try { if (s.impl == null) s.setImpl(); else { s.impl.reset(); } si = s.impl; s.impl = null; si.address = new InetAddress(); si.fd = new FileDescriptor(); getImpl().accept(si); SocketCleanable.register(si.fd); // raw fd has been set SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkAccept(si.getInetAddress().getHostAddress(), si.getPort()); } } catch (IOException e) { if (si != null) si.reset(); s.impl = si; throw e; } catch (SecurityException e) { if (si != null) si.reset(); s.impl = si; throw e; } s.impl = si; s.postAccept(); } ... }
- 실제 데이터 송수신 담당
- 두 machine 사이 통신의 endpoint
package java.net;
class Socket implements java.io.Closeable {
...
/**
/* 사용자 정의 SocketImpl으로 unconnected Socket을 생성
**/
protected Socket(SocketImpl impl) throws SocketException {
checkPermission(impl);
this.impl = impl;
if (impl != null) {
checkOldImpl();
this.impl.setSocket(this);
}
}
...
/**
/* 해당 Socket에 대한 input stream 반환
**/
public InputStream getInputStream() throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
if (!isConnected())
throw new SocketException("Socket is not connected");
if (isInputShutdown())
throw new SocketException("Socket input is shutdown");
InputStream is = null;
try {
is = AccessController.doPrivileged(
new PrivilegedExceptionAction<>() {
public InputStream run() throws IOException {
return impl.getInputStream();
}
});
} catch (java.security.PrivilegedActionException e) {
throw (IOException) e.getException();
}
return is;
}
/**
/* 해당 Socket에 대한 output stream 반환
**/
public OutputStream getOutputStream() throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
if (!isConnected())
throw new SocketException("Socket is not connected");
if (isOutputShutdown())
throw new SocketException("Socket output is shutdown");
OutputStream os = null;
try {
os = AccessController.doPrivileged(
new PrivilegedExceptionAction<>() {
public OutputStream run() throws IOException {
return impl.getOutputStream();
}
});
} catch (java.security.PrivilegedActionException e) {
throw (IOException) e.getException();
}
return os;
}
...
}