프로그래밍[Univ]/기타

[시스템프로그래밍] IPC(Inter Process Communication) Part 2 Socket, Semaphores

Cloud Travel 2012. 11. 7. 18:17

* Socket

 - 서로 다른 System에 속한 프로세스간의 통신을 위해서 탄생하였다.

 - Socket은 프로세스간의 통신을 위환 출입구 역할을 한다.

 - Pipe, FIFO와 같은 형식으로 파일 디스크립터를 이용하여 접근을 한다.

 - Socket은 생성과 동시에 필요하다면, Socket에 이름을 붙여서 관리한다.

 - Socket의 종류에는 Virtual circuit과 Data-gram방식이 존재한다.

 

* Socket - ⓐ Virtual circuit - stream socket

 - 네트워크의 Circuit switch방식을 생각하면 된다.

 - 통신 대상은 서로를 연결하는 네트워크를 연결하고, 그 라인을 점유한다.

 - 송수신이 끝날때까지 이 라인은 유지되며, 송수신이 끝나면 라인은 회수된다.

 - 대량의 데이터를 송수신하는 경우에 많이 사용된다.

 - 장점 

  > 통신의 신뢰성이 보장된다.(데이터 순서 보장, 패킷 손실 없음)

 - 단점

  > 특정 라인을 점유하기 때문에 전체 네트워크 시스템에 부하를 준다.

  > 이 때문에 대용량 데이터 전송이나 사용 빈도가 적은 경우에만 사용 한다.

 - 소켓 연결 및 진행 순서

     

 ⓐ int socket(int domain, int type, int protocol)

  - 각각의 프로세스는 자신의 소켓을 생성한다.

  - domain : 사용하는 도메인 종류(PF_UNIX : UNIX domain // PF_INET : inet domain)

  - type : 사용하는 소켓의 종류(Sock_stream : stream socket // Sock_dgram : datagram socket)

  - protocol : 사용되는 고유의 protocol로 대부분 0을 사용한다.

  - 수행이 제대로 된다면 socket의 file descriptor를 반환하고 그렇지 않으면 -1을 반환한다.

 ⓑ int bind(int sock_fd, struct sockaddr *my_addr, int len)

  - 각각의 프로세스는 소켓을 만들면 그것에 이름을 붙일 수 있다.(생략 가능)

  - sock_fd : 자신의 소켓의 파일 디스크립터

  - *my_addr : 이름을 붙일 구조체

  - len : 이름의 길이

  - bind() 수행이 제대로 된다면 0을 그렇지 않으면 -1을 반환한다.

 ⓒ int listen(int sock_fd, int backlog)

  - 프로세스 자신이 서버라면, 누군가가 자신에게 접속을 시도할 것을 알고 있기 때문에, 귀를 열고 기다린다.

  - sock_fd : 서버 자신의 socket 파일 디스크립터

  - backlog : 서버로의 요청은 여러 Client로부터 connect를 받아 주기 위한 대기열의 수

  - server 프로세스는 호출이 정상 실행 되면 0을 에러시 -1을 반환한다.

 ⓓ int connect(int sock_fd, const struct socketaddr * serv_addr, socklen_t addr_len)

  - 자신이 client라면, 서버가 들은 준비가 된 것을 알게 되면 접속을 요청할 것이다.

  - sock_fd : client자신의 socket 파일 디스크립터

  - *serv_addr : 서버의 소켓 주소 정보

  - addr_len : 소버 소켓 주소 정보 구조체의 길이

  - 요청이 정상 수행되면 0을 반환, 그렇지 않으면 -1을 반환

 ⓔ int accept(int sock_fd, struct sockaddr *client_addr, socklen_t *addr_len)

  - 서버는 client의 요청을 수락한다.

  - sock_fd : 자신의 소켓 파일 디스크립터

  - client_addr : 클라이언트의 소켓 주서 정보

  - addrlen : 클라이언트의 소켓 주서 정보 구조체의 길이

  - accpet()수행이 올바르게 수행되었다면 새로운 소켓을 생성하며, 그 소켓의 파일 디스크립터를 반환

  ※ 새로운 디스크립터를 만드는 이유

   > stream방식의 경우 accept단계가 필요한 것인데, 하나의 소켓으로는 하나의 클라이언트만 통신이 가능하다.

   > 여러명의 클라이언트와 통신을 하기 위해서 accept할 때마다 새로운 socket을 생성하여 IPC를 실시한다.

 ⓕ 연결이 다 되었으므로 서버와 클라이언트는 send()/recv() or write()/read()를 이용하여 통신을 하면된다.

  - int send(int sock_fd, const void *buf, size_t len, int flags)

   > sock_fd : 통신에 사용되는 소켓의 파일 디스크립트 번호(server : accpet()반환 값/client : socket()반환값)

   > buf : 송신 버퍼의 시작 주소

   > len : 송신 데이터의 길이

   > flags : 송신 옵션 

  - int recv(int sock_fd, void *buf, size_t len, int flags)

   > sock_fd : 통신에 사용되는 소켓의 파일 디스크립트 번호(server : accpet()반환 값/client : socket()반환값)

   > buf : 수신 버퍼의 시작 주소

   > len : 수신 데이터의 길이

   > flags : 수신 옵션 


* Socket - ⓑ Datagram - Datagram socket

 - 네트워크의 packet switch방식을 생각하면된다.
 - Virtual circuit과 다르게 서로의 전용 선로를 설정할 필요가 없다.
 - 각각의 데이터는 그때 그때 상대방에게 보내지게 된다.
 - 프로세스간 작은 데이터를 계속해서 보내는 통신
 - 데이터의 신뢰성은 보장되지 않는다.(순서가 뒤바뀔 가능성이 존재)
 - 소켓의 진행 순서
  

 ⓐ int socket(int domain, int type, int protocol)

  - 각각의 프로세스는 자신의 소켓을 생성한다.

  - domain : 사용하는 도메인 종류(PF_UNIX : UNIX domain // PF_INET : inet domain)

  - type : 사용하는 소켓의 종류(Sock_stream : stream socket // Sock_dgram : datagram socket)

  - protocol : 사용되는 고유의 protocol로 대부분 0을 사용한다.

  - 수행이 제대로 된다면 socket의 file descriptor를 반환하고 그렇지 않으면 -1을 반환한다.

 ⓑ int bind(int sock_fd, struct sockaddr *my_addr, int len)

  - 각각의 프로세스는 소켓을 만들면 그것에 이름을 붙일 수 있다.(생략 가능)

  - sock_fd : 자신의 소켓의 파일 디스크립터

  - *my_addr : 이름을 붙일 구조체

  - len : 이름의 길이

  - bind() 수행이 제대로 된다면 0을 그렇지 않으면 -1을 반환한다.

 ⓒ 각각의 소켓을 dagagram방식으로 열었다면 특정한 연결 없이 상대방을 적어서 메세지를 보내면 된다.

  - int sendto(int sock_fd, const void *buf, size_t len, int flgs, const struct sockaddr *to, socklen_t tolen)

   > sock_fd : 통신에 사용되는 소켓의 파일 디스크립트 번호(server : accpet()반환 값/client : socket()반환값)

   > buf : 송신 버퍼의 시작 주소

   > len : 송신 데이터의 길이

   > flags : 송신 옵션 

   > *to : 받을 곳의 소켓 주소 정보 구조체

   > tolen : 구조체의 길이

  - int recvfrom(int sock_fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)

   > sock_fd : 통신에 사용되는 소켓의 파일 디스크립트 번호(server : accpet()반환 값/client : socket()반환값)

   > buf : 수신 버퍼의 시작 주소

   > len : 수신 데이터의 길이

   > flags : 수신 옵션 

   > *from : 보낸 곳의 소켓 주소 정보를 가르키는 구조체

   > tolen : 소켓 주소 정보 구조체의 길이


* Semaphores

 - IPC를 하는 직접적인 요소는 아니다.

 - IPC를 하는 과정에서 서로 공유되는 데이터를 사용할 경우 그 데이터에 대한 접근을 통제하기 위해서 사용된다.

 Semaphore sv = 1;

 Loop true{

      P(sv);

//critical section

V(sv);

// non-critical section

 }

 - P(sv) : if value > 0, then value-- critical section에 접근

  > critical section의 사용가능 여부를 check(value > 0)하고 , 다른 프로세스가 접근하지 못하게한다(value--)

 - V(sv) : value++

  > critical section의 사용이 끝나면, 다른 프로세스가 접근이 가능하게 value값을 변경한다.

  >>> 위 예에서 value 값은 sv

 - 대기중인 프로세스의 행동

  ⓐ sleep wait : 프로세스는 대기상태에서 나가는 프로세스가 깨워주기를 기다린다.(overhead)

  ⓑ busy wait : 프로세스는 critical section에 대해 접근이 가능한지 계속 확인한다.(overhead)

   >> critical section을 잡는 속도가 busy wait 방식이 더 빨라서 대부분 busy wait 방식을 사용한다.