6/28/2007

[Network] TCP 서버 프로그램 작성시 사용되는 함수들

** TCP 서버 프로그램 작성시 사용되는 함수들

- 서버용 struct sockaddr_in 구조체의 주소에서 INADDR_ANY 값을 볼 수 있다. 클라이언트용 sockaddr_in 구조체의 주소 값에는 접속한 서버의 IP 주소를 넣게 되지만, 서버용 sockaddr_in 구조체의 주소 값에는 접속될 클라이언트, 즉 자신에게 접속할 클라이언트의 주소를 넣게 되어 있다. 서버용 struct sockaddr_in에 특정 IP 주소를 넣으면 해당 클라이언트에서만 접속할 수 있는 문제가 생기므로 INADDR_ANY 값을 넣어서 모든 클라이언트에서 접속할 수 있게 만든다.

- INADDR_ANY 값은 0으로 정의되어 있다.

#define INADDR_ANY ((unsigned long int) 0x00000000)

- INADDR_ANY 값을 넣을 때 사용하는 htonl 함수는 htons 함수와 비슷하게 long형 숫자에 네트워크 바이트 오더를 적용해서 반환하는 역할을 한다. htons 함수는 short형 숫자를 변환할때 사용하지만 htonl 함수는 long형 숫자를 변환할 때 사용한다.


* htonl 함수 : 32비트 네트워크 바이트 오더형 숫자 htonl (32비트 호스트 오더형 숫자)

-> 32비트의 호스트 오더형 숫자를 네트워크 바이트 오더의 숫자로 변경한다. 인텔 CPU에서는 리틀 엔디안인 32비트 숫자 변수를 네트워크 바이트 오더인 빅 엔디안을 적용한 후 반환한다.

#include <netinet/in.h>
uint32_t htonl (uint32_t hostlong)


* bind 함수 : 성공 여부 반환 bind (소켓 디스크립터, 로컬 주소, 로컬 주소 구조체 크기)

-> 생성된 소켓에 로컬 주소를 할당한다. 로컬 주소에 설정할 수 있는 옵션은 연결될 클라이언트의 주소 패밀리, IP 정보, 포트 정보가 있다. 성공하면 0을 반환하고 오류가 발생하면 -1을 반환하면서 errno에 오류 번호를 넣는다.

#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)


* listen 함수 : 성공 여부 반환 listen (소켓 디스크립터, 최대 연결할 큐의 길이)

-> 해당 소켓에서 연결을 기다린다. 연결의 큐의 길이만큼만 가능하며 일반적으로 5를 많이 사용한다. 성공하면 0을 반환하고 오류가 발생하면 -1을 반환하면서 errno에 오류 번호를 넣는다.

#include <sys/socket.h>
int listen(int s, int backlog)


* accept 함수 : 성공한 소켓 디스크립터 accept (소켓 디스크립터, 접속한 상대편 연결 정보, 연결 정보 길이)

-> 해당 소켓에 연결 요청이 들어왔을 때 연결을 받아들인다. 연결 요청이 없는 경우에는 연결 요청이 발생할 때까지 대기 상태에서 해당 소켓을 계속 감시한다. 오류가 발생하면 -1을 반환하고 연결에 성공하면 해당 소켓 디스크립터인 음이 아닌 정수를 반환한다.

#include <sys/types.h>
#include <sys/socket.h>
int accept(int s, struct sockaddr *addr, socklen_t *addrlen)


* write 함수 : 성공 시 쓰여진 데이터 길이 write (파일 디스크립터, 전송할 버퍼, 전송할 데이터 길이)

-> 버퍼에서 데이터를 읽어서 파일 디스크립터에 인수로 주어진 크기만큼 쓴다. 쓰기에 성공하면 쓰기에 성공한 길이를 반환하고 오류가 발생하면 -1을 반환하면서 errno에 오류 번호를 넣는다.

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count)


* close 함수 : 성공 여부 반환 close (파일 디스크립터)

-> close 함수는 파일 디스크립터를 닫는다. 닫혀진 파일 디스크립터는 더 이상 어떤 파일에 의해서 참조되거나 사용될 수 없다. 닫기에 성공하면 0을 반환하고 오류가 발생하면 -1을 반환한다.

#include <unistd.h>
int close(int fd)

[Network] TCP(Transmission Control Protocol)

** TCP(Transmission Control Protocol)

- 세션관리

- 핸드셰이크

- 패킷 순서 조합

- 포트를 이용한 서비스 다중화


- 세션 : 서버가 해당 클라이언트와 데이터 통신을 하기 위해서 제공하는 전용 통로. 클라이언트에 따라서 구분되어 있는 연결 관리는 서로 다른 클라이언트에서 전송한 패킷이 충돌되는 것을 방지함으로써 인터넷에서 데이터의 전송을 안전하게 보장해 준다.

[Network] TCP 클라이언트 프로그램 작성시 사용되는 함수들

** TCP 클라이언트 프로그램 작성시 사용되는 함수들

* socket 함수 : 소켓 지정자 socket(인자 도메인, 소켓의 형태, 프로토콜 종류)

-> 해당 소켓을 생성하고 소켓의 디스크립션을 반환한다.

#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol)

- 인자 도메인 : 통신 도메인을 지정하는 인자로서 네트워크의 종류라고 생각하면 된다. 네트워크에는 노벨 IPX, ATM, X.25, IPv6 그리고 TCP 클라이언트 프로그램에서 사용하려고 하는TCP/IP 네트워크 등이 있다.

* 리눅스에서 정의되어 있는 프로토콜 패밀리 목록

PF_UNSPEC
PF_UNIX : 유닉스 도메인 소켓
PF_LOCAL : PF_UNIX 소켓의 포직스 표현
PF_INET : 인터넷 프로토콜
PF_AX25 : 아마추어 라디오 AX.25
PF_IPX : 노벨 IPX
PF_APPLETALK : 애플토크 DDP
PF_NETROM : 아마추어 라디오 NET/ROM
PF_BRIDGE : 다중 프로토콜 브리지
PF_ATMPVC : ATM PVCs
PF_X25 : X.25 프로젝트를 위해 예약
PF_INET6 : IPv6 프로토콜
PF_ROSE : 아마추어 라디오 X.25 PLP
PF_DECnet : DECnet 프로젝트를 위해 예약
PF_NETBEUI : 802.2LLC 프로젝트를 위해 예약
PF_SECURITY : 보안 콜백 주소 패밀리
PF_KEY : 키 관리 API
PF_NETLINK : 4.4BSD 에뮬레이트
PF_ROUTE : 4.4BSD 에뮬레이트
PF_PACKET : 패킷 패밀리
PF_ASH : Ash
PF_ECONET : Acorn Econet
PF_ATMSVC : ATM SVCs
PF_SNA : 리눅스 SNA 프로젝트
PF_IRDA : 적외선(IrDA) 소켓
PF_PPPOX : PPPoX 소켓
PF_WANPIPE : Wanpipe API 소켓
PF_LLC : 리눅스 LLC
PF_BLUETOOTH : 블루투스 소켓

- 표준 문서에서는 도메인을 지정할 경우에는 프로토콜 패밀리(PF_)를 사용하고, 도메인 인자를 지정할 때는 주소 패밀리(AF_)를 사용하도록 권장하지만 서로 바꾸어 사용하더라도 같은 값이기 때문에 문제는 발생하지 않는다.

- 소켓의 형태 : 소켓의 연결 형식을 정의. SOCK_STREAM, SOCK_DGRAM, SOCK_RAW 가 있다.

- SOCK_STREAM : TCP/IP 인터넷 프로토콜에서 TCP를 통해서 전송되는 신뢰성 있는 연결을 의미한다. TCP는 핸드셰이크라는 과정을 통해서 데이터를 전송할 때마다 해당 데이터를 잘 받았다는 확인 패킷을 받는다. TCP는 데이터를 전송할 때마다 확인 패킷을 받고 확인 패킷이 일정주기 이상 들어오지 않으면 상대편 종단과의 연결을 종료한다. TCP는 신뢰성 있는 연결 때문에 채팅, 게임, 인터넷, 등의 신뢰성이 필요한 분야에서 많이 사용한다.

- SOCK_DGRAM : TCP/IP 인터넷 프로토콜에서 UDP를 통해서 전송하는 신뢰성이 없는 연결을 의미한다. UDP는 데이터를 인터넷을 전송한 후 상대편에게 데이터를 잘 도착했는지 확인하지 않는다. UDP는 데이터를 전송하고 그 데이터의 도착 여부를 확인하지 않기 때문에 신뢰성이 보장되지 않아도 되는 동영상이나 오디오 스트림 서비스, 속도에 민감한 프로토콜의 설계에서
많이 사용한다.

- SOCK_RAW : TCP/IP 인터넷 프로토콜의 헤더를 우리가 직접 만들어 주어야 하는 것을 의미한다. SOCK_STREAM이나 SOCK_DGRAM은 해당 인터넷 프로토콜에 맞추어서 TCP/IP 인터넷 프로토콜의 헤더를 운영체제에서 자동으로 만들어 주지만 SOCK_RAW의 경우는 이런 헤더를 우리가 직접 만들어 주어야 한다. 이런 연결 방식은 특별한 형식의 패킷을 만들어서 네트워크에 전송한다거나 자신에게 전송되는 패킷을 모두 캡처하는 용도로 사용할 수 있다. RAW 소켓을 이용한 예로, 상대방의 통신 연결 상태를 확인하는 Ping 프로그램을 들 수 있다.

- socket 함수는 인자 값을 받아 소켓을 생성한 후에 해당 소켓의 지정자를 반환한다. 그리고 오류가 발생한 경우에는 소켓 지정자에 0보다 값을 반환하고 소켓 생성에 성공한 경우에는 소켓에 할당된 번호인 소켓 지정자를 반환한다.


* 바이트 오더(Byte Order) : 데이터의 저장되는 방식에 따라서 데이터 순서가 바뀌는 것.

- 리틀 엔디안(Little Endian) : 메모리에 데이터를 저장할 때 하위 비트의 데이터를 먼저 저장하는 방식(인텔 펜티엄 PC)

- 빅 엔디안(Big Endian) : 메모리에 데이터를 저장할 때 상위 비트의 데이터를 먼저 저장하는 방식


* inet_addr 함수 : 이진 바이너리 형식의 IP 주소 inet_addr (문자 형식의 IP 주소)

-> 문자 형식의 IP 주소를 네트워크 바이트 오더를 적용한 이진 바이너리 코드로 바꾸어 반환한다.

#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
unsigned long int inet_addr (const char *p)


* htons 함수 : 네트워크 바이트 오더가 적용된 이진 바이너리 16비트 값 htons (16비트 변수값)

-> 16비트의 unsinged short형 숫자 값에 네트워크 바이트 오더를 적용한 후 반환한다.

#include <netinet/in.h>
uint16_t htons(uint16_t hostshort)


* connect 함수 : 리턴 값 connect (소켓 디스크립션, 서버의 IP 주소와 포트번호, 길이)

-> 소켓 연결을 시작한다. 생성된 소켓과 서버의 정보를 이용해서 해당 서버에 연결한 후 결과값을 리턴한다. 0이면 성공, -1이면 실패를 의미한다.

#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)


* read 함수 : 읽은 값의 길이 read (파일 디스크립터, 읽은 데이터를 저장할 버퍼, 읽을 데이터 최대 길이)

-> 지정된 파일 디스크립터에서 데이터를 읽어서 지정된 버퍼에 데이터를 넣은 후 읽은 데이터의 길이를 반환한다. 오류가 발생하면 -1을 반환한다.

-> 네트워크 프로그래밍에서 파일 디스크립터에 해당하는 것이 소켓 디스크립터다. 소켓 디스크립터는 socket 함수가 반환하는 소켓의 번호를 의미하며 우리는 이것을 소켓 지정자라 한다.

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count)


* close 함수 : 성공 여부 반환 close (파일 디스크립터)

-> close 함수는 파일 디스크립터를 닫는다. 닫힌 파일 디스크립터는 더 이상 참조되거나 사용될 수 없다. 닫기에 성공하면 0을 반환하고 오류가 발생하면 -1을 반환한다.

#include <unistd.h>
int close(int fd)

6/25/2007

[Network] internet vs Internet

* internet vs Internet

- internet : 두 개 이상의 네트워크가 연결될 때 칭하는 말로서 인터네트워크(internetwork)의 준말.

- Internet : 일반적으로 말하는 인터넷으로 전세계를 포함하는 ALPHANET에서 유래한 특정 거대 네트워크를 지칭하는 명사.

- 네트워크 : 두 대 이상의 정보 단말기가 연결되어 있는 경우를 지칭

- 인터넷 : 네트워크가 인터네트워킹 장치(라우터, 게이트웨이 등)에 의해 두 개 이상 연결된 것

* 중계기(repeater or regenerator) : 링크(케이블)를 연결하는 데 있어서 잡음 등으로 인해 약해진 신호를 원래의 비트로 재생하는 역할을 수행

* 브리지(bridge) : 규모가 큰 네트워크를 좀더 작은 단위인 세그먼트(segment)로 분리할 때 사용된다. 여기서 세그먼트란 하나의 네트워크를 브리지 등을 사용해서 분리했을 때 그 각각을 지칭하는 단위. 브리지는 각 세그먼트간의 프레임(데이터그램에 물리 헤더가 붙은 것을 프레임이라 하는데, 쉽게 설명하면 NIC에서 케이블을 통해 나가는 패킷이라고 보면 된다.)

* 라우터(router) : 네트워크 주소(IP)를 이용해서 데이터를 최적의 경로로 찾아가게 하는 장치. 라우터는 네트워크와 네트워크를 연결할 때 사용되는데, 라우터의 역할은 단순히 네트워크만 연결하는 것이 아니라 특정한 네트워크의 단말기가 다른 네트워크로 패킷을 전송하고자 할때 패킷이 전송될 최적의 경로를 판단해서 패킷을 중계하는 역할도 담당한다.

* 게이트웨이(gateway) : '프로토콜 변환기'라고도 하는데, 서로 다른 프로토콜을 사용하는 네트워크를 연결할 때 사용된다. 게이트웨이는 기본적으로 라우터의 기능을 포함하고 있으며 거기에 추가적으로 각 네트워크에서 사용되는 프로토콜이 다르면 프로토콜을 변환하는 역할까지 담당한다.

* 스위치 : 브리지가 내장되어 있는 가장 대표적인 장치가 스위치며, 스위치는 허브처럼 생겼고 허브가 하는 일을 그대로 수행한다. 하지만 스위치는 허브와 다르게 각각의 포트에 대해서 브리지로 분리시켜 놓았기 때문에 네트워크 트래픽이 감소해서 모든 단말기에 회선 대역폭을 제공할 수 있고 또한 각 단말기가 세그먼트 단위로 분리되기 때문에 보안성이 좋다.

* 프로토콜 스택 : 운영체제에서 지원하는 프로토콜 소스

- 잘 알려진 포트 : 0~1023
- 등록된 포트 : 1024~49151
- 동적인 또는 사적인 포트 : 49152~65535

[Network] 서버, 클라이언트 프로그램 함수 흐름 순서

* 서버 프로그램 함수 흐름 순서

socket -> bind -> listen -> accept -> wirte -> close

- socket : 소켓을 생성한다.

- bind : 주소 구조체인 server_addr 설정 값으로 서버 소켓의 주소를 설정한다.

- listen : 클라이언트의 접속을 기다린다.

- accept : 접속한 클라이언트로 소켓을 반환한다.

- write : 클라이언트 소켓으로 데이터를 전송한다.

- close : 소켓을 닫는다.


* 클라이언트 프로그램 함수 흐름 순서

socket -> connect -> read -> close

- socket : 소켓을 생성한다.

- connect : 지정한 주소로 접속한다.

- read : 서버 프로그램에서 전송하는 문자열을 받아서 buf 변수에 저장한다.

- close : 소켓을 닫는다.