Socket이 왜 나왔는가?
:socket
이다.int s = socket(domain, type, protocol)
:
file을 open하는 것처럼, socket도 open해야 함.
s = sockid
: socket descriptor. (열리는 socket은 모두 고유한 socket identifier를 갖는다.)domain
: communication domain(PF_INEF = IPv4 protocol -> typically used)type
:SOCK_STREAM
: socket을 TCP로 만들 것이다.SOCK_DGRAM
: socket을 UDP로 만들 것이다.protocol
: specifies protocol (usually set to 0)socket(2)
으로 socket을 열면, 열릴 수도 있고 안열릴 수도 있다.
port number
도 필요하다.int status = bind(sockid, &addrport, size)
:sockid
: sock(2) system call에 대한 반환값. socket descriptor.addrport
: size
: the size(bytes) of the addrport structure.Passive participant & Active participant Connection Setup Flow
:int status = listen(sock, queuelen)
:status
: 0 if listening, -1 if errorsock
: socket descriptorqueuelen
: client의 request를 몇 개까지 기다릴 것인가?int s = accept(sock, &name, &namelen)
:s
: connection을 request한 client랑만 통신하기 위해 server에 생성되는 new socket's descriptor. (accept socket)sock
: 기존 server에서 client들의 request를 listen()하기 위한 socket. 또 다른 client와의 연결을 위해 계속 listen. (Listen socket)&name
: sockaddr형 구조체를 넣음. (해당하는 client의 ip address와 port number에 대한 정보가 들어가 있음.)&namelen
: sizeof(name)int status = connect(sock, &name, namelen)
:status
: 0 if successful connect, -1 otherwisesock
: client's socket descriptor&name
: sockaddr 구조체에다가 값을 직접 써야 함. (server의 IP address & port)namelen
: sizeof(name)SOCK_STREAM
: With a connection
int count = send(sock, &buf, len, flags)
:
count
: #bytes transmitted (-1 if error)sock
: client의 request에 의해 생성된 server의 accept socket descriptor&buf
: char[], bffer to be transmitted len
: length of buffer to transmitflags
: special optionsint count = recv(sock, &buf, len, flags)
:
count
: # bytes received (-1 if errors)sock
: client의 socket? server의 accept socket?buf
: void[]->(type casting), stores received byteslen
: #bytes receivedflags
: speical optionsrecv(2)는 blocking io이다.
blocking io는 그 함수를 실행했을 때, 어떤 조건을 만족하지 않으면 그 함수에서 계속 blocking이 되어 있음. (ex: scanf(3))
나중에 이 blcoking io가 발목을 잡음...
SOCK_DGRAM
: Without a connectionint count = sendto(sock, &buf, len, flags, &addr, addrlen)
sock
: server에 있는 1개의 socket&addr
: struct sockaddr (server의 IP address)int count = recvto(sock, &buf, len, flags, &addr, &addrlen)
정리)
SOCK_STREAM(TCP)에서는 Client A가 accept socketA에만 send, receive를 할 수 있다.
SOCK_DGRAM(UDP)는 하나의 socket을 Client A, Client B 등이 send, receive를 할 수 있다.
status = close(s)
:이 flow는 모든 platform, 모든 language에서 동일함
TCP Flow
:UDP Flow
:structure sockaddr의 구조
:sin_family
: AF_INET(IPv4)sin_port
: port # (0 - 65535)sin_addr
: IP addresssin_zero
: unusedsin_port
, sin_addr
만 써도 된다.최근에는 내부적으로 Byte-ordering을 하기 위해서 host byte order라는 program이 실행되고 있어서 크게 상관하지 않는다.
Big-Endian machine
:
Little-Endian machine
:
Blocking I/O
:
Blocking I/O 밑에 아무리 중요한 code를 작성했더라도
blocking되어 있으면, 밑의 code는 실행되지 않음.
ex : accept(), connect(), recv(), recvfrom(), send(), sendto()
program을 작성할 때, Blocking I/O를 사용하면 편리하긴 하다.
Reliable data transfer할 때, Stop and Wait로 예시를 들면
data 하나 보내고 그게 완전히 처리될 때까지 기다렸다가 다음 data 보내고... 하면 되니까 생각할게 없었음.
하지만 blocking이 풀린 pipeline 방식으로 바뀌면서 복잡해졌다.
➡️ 이처럼 Blocking I/O를 사용하면 program 작성이 편리하긴 하지만, 복잡한 system에서는 문제가 발생한다.
multiple conection일 때
simultaneous sends and receives가 안 된다
non-networking processing
int status = select(nfds, &readfds, &writefds, &exceptfds, &timeout)
:status
: # of ready objects, -1 if errornfds
: 1 + largest file descriptor to check&readfds
: list of descriptors to check if read-ready&writefds
: list of descriptors to check if write-readyexceptfds
: list of descriptors to check if an exception is registeredtimeout
: time after which select returns, even if nothing ready - can be 0 or