11 소켓
- 11.1 소켓 개념
- 11.2 통신스타일
- 11.3 소켓 주소
- 11.4 The File Namespace
- 11.5 인터넷 이름공간
- 11.6 다름 이름공간들
- 11.7 소켓 열고 닫기
- 11.8 연결하는데 소켓사용
- 11.9 데이터그램 소켓 명령
- 11.10 inetd 데몬
- 11.11 소켓 옵션
- 11.12 네트워크 데이터베이스
이 장에서는 소켓을 사용하여 프로세스간의 통신에 관한 GNU장치에 대해 서술한다.
소켓은 일반적인 프로세스간의 통신 채널이다. 파이프처럼 소켓은 파일 서술자처럼 표현된다. 그러나 파이프와는 달리 소켓은 관련 없는 프로세스간의 통신, 네트워크를 통하여 서로 다른 컴퓨터에서 수행되고 있는 프로세스간의 통신을 제공한다. 소켓은 주로 다른 컴퓨터간의 통신의 수단이다. telnet, rlogin, ftp, talk, 그리고 네트워크 프로그램들은 소켓을 사용한다. 모든 운영체제가 소켓을 지원하는 것은 아니다. GNU라이브러리에서 'sys/socket. h' 은 운영체제와 상관없이 존재한다. 그러나 만약 시스템이 소켓을 지원하지 않는다면, 소켓함수는 항상 실패한다.
미완성: 우리는 현재 인터넷 인터페이스 설정이나 브로드캐스트 메시지기능에 관하여는 문서화하지 못했다.
당신이 소켓을 만들 때, 반드시 당신이 어떤 통신 스타일을 쓸 것인지, 어떤 프로토콜을 사용할 것인지 명시해야 한다. 소켓의 통신 스타일은 소켓으로 데이터를 보내고 받는 유저레벨 구문을 정의한다. 통신 스타일을 선택하는 것은 다음과 같은 질문의 응답이 된다. 데이터 전송의 단위는 무엇인가?
보통 작업을 하는 동안에 데이터를 잃어버릴 수 있나?
상대측과 완전한 통신을 하느냐?
두 소켓간의 통신을 위하여, 그것들은 반드시 같은 프로토콜을 나타내야 한다.
GNU라이브러리는 각기 다른 특성을 지닌 몇 종류의 소켓을 지원하고 있다. 이 절에서는 지원되는 소켓 형태를 서술한다. 여기 나타난 심볼릭 상수는 'sys/socket. h'에 정의되어 있다. int SOCK_STREAM Macro
int SOCK__DGRAM Macro
int SOCK__RAW Macro
소켓의 이름은 보통 "주소"라고 불린다. 소켓주소와 관계된 기호(symbol)와 함수들은, 때때로 "이름"이라는 말이나 "주소"를 사용되어, 어떤 규칙 없이 이름 지어진다. 당신은 소켓이 고려되는 곳에 이러한 말을 동일한 것처럼 생각할 수 있다. socket함수로 새롭게 만든 소켓은 주소를 가지지 않는다. 당신이 그것에게 주소를 주어야만, 다른 프로세스가 통신을 위한 주소를 찾을 수 있게 된다. 이것을 주소를 소켓에 묶는다고 하고, bind함수를 이용한다. 만약 다른 프로세스들이 주소일 찾고, 주소를 이용하여 통신을 시작하는 것이라면, 당신은 소켓의 주소를 생각해 볼 필요가 한다. 당신은 다른 소켓의 주소를 규명할 수 있지만, 그것은 보통 무의미하다; 처음, 소켓으로부터 데이터를 보내거나 연결을 초기화하기 위해 그것을 사용할 때, 만약 구체적으로 나타내진 것이 없다면, 시스템은 주소를 자동으로 설정한다. 서버는 주소에 기초하여 판별되기 때문에, 보통 클라이언트는 주소를 명시해야 한다. ; 예를 들어, rsh 와 rlogin 프로토콜은 클라이언트의 소켓주소를 살피고, 만약 그것이 IPPORT_RESER VED보다 작지 않다면, 암호검사를 거쳐야 한다. ( 11.5.3절의 [포트] 을 보라) 소켓주소의 자세한 것은 당신이 사용하는 어떤 이름공간에 의존하여 변한다. 자세한 정보를 위해서는 11. 4절 [파일 이름공간] 을 보거나, 11. 5절 [인터넷 이름공간] 참조. 이름공간에 상관없이 , 소켓의 주소를 세트하고 사용하기 위해 당신은 같은 bind와 getsockname함수를 사용한다. 이러한 함수들은 주소를 받아들이기 위해 struct sockaddr *라는 위조 자료형(phony data type)을 사용한다. 실제적으로, 주소는 당신이 사용하는 주소포맷과는 다른 자료형의 구조로 되어 있다. 그러나, 당신은 그것을 bind하기 위해 넘겨줄 때, 그것의 주소를 struct sockaddr *로 자료형 변환(cast)을 해주어야 한다. bind와 getsockname함수는 소켓의 주소의 포인터를 의미하는 struct sockaddr *이라는 일반적인 자료형을 사용한다. 당신은 주소를 번역하거나 만들기 위해 이 자료형을 효율적으로 사용할 수 없다; 대신, 소켓의 이름공간을 위한 자료형을 사용해야만 한다. 그러므로, 보통 실제적인 사용은 적합한 이름공간의 형태의 주소를 만드는데 사용하고 나서, bind나 getsockname을 호출할 때 struct sockaddr *로 포인터형태를 변환한다. 당신이 struct sockaddr 자료형으로부터 얻을 수 있는 정보 중 하나는, 주소를 완전히 이해하기 위해 사용되는 자료형이 어떤 것인지 알려주는 "주소 포맷" 지정자이다. 이 절에서의 기호는 'sys/socket. h'라는 헤더파일안에 정의되어 있다. struct sockaddr 자료형 struct sockaddr형 자체는 다음 멤버를 가지고 있다: short int sa_family
char sa_data[14]
AF_FILE
AF_UNIX
AF_INET
AF_UNSPEC
소켓에 주소를 할당하기 위하여 bind함수를 사용하라. bind의 프로토타입은 'sys/socket. h'헤더파일에 있다. 사용예는 11. 4절[파일 이름공간], 또는 11. 5. 7절[Inet 예제] 을 보라. int bind (int socket, struct sockaddr *addr, size_t length) Function
EBADF : 소켓 인수가 유효하지 않은 파일 지정자이다. ENOTSOCK : 서술자 socket이 소켓이 아니다. EADDRNOTAVAIL : 지시된 주소가 이 장치에서는 유효하지 않다. EADDRINUSE : 또 다른 소켓이 이 주소로 이미 사용되고 있다. EINVAL : socket소켓이 이미 주소를 가지고 있다. EACCESS
추가적인 조건은 소켓의 각각 이름공간에 의존한다. getsockname함수를 사용하여, 인터넷 소켓의 주소를 확인할 수 있다. 이 함수의 프로토타입은 'sys/socket. h'라는 헤더파일에 있다. int getsockname (int socket, struct sockaddr *addr, size_t *length_ptr) 함수
EBADF : 소켓인수가 유효한 파일 서술자가 아니다. ENOTSOCK : 서술자 socket이 소켓이 아니다. ENOBUFS
이 부분은 상징적인 이름(소켓을 만들 때 요구하는) 은 PF_FILE이라는 파일 이름공간에 대해 상세히 설명한다. 파일이름공간에서, 소켓 주소는 파일 이름들이다. 당신은 소켓의 주소처럼 당신이 원하는 어떤 파일 이름을 명시할 수 있다. 그러나 당신은 반드시 그것을 포함하는 디렉토리에 쓰기 허가를 가지고 있어야 한다. 소켓에 연결하기 위해, 당신은 그것에 대한 읽기 허가도 가지고 있어야 한다. 보통 /tmp디렉토리 안에 그러한 파일들을 넣는다. 파일이름공간의 특별한 점 하나는 연결을 할 때 그 이름이 한 번만 사용된다는 것이다. 즉, 그것을 한 번 사용하고 나면, 그 주소는 의미가 없고, 존재하지 않을지도 모른다. 또 다른 특징은 만약 소켓의 이름을 포함하는 파일시스템을 다른 기기가 공유하지 않는다면 다른 기기의 어떤 소켓으로 연결할 수 없다는 것이다. 당신은 디렉토리 리스트 안에서 소켓을 볼 수 있으나, 그것에 연결하는 것은 불가능하다. 어떤 프로그램들은 클라이언트가 자기 프로세스 ID를 보내도록 요구하는 것과 프로세스ID를 사용하여 클라이언트간을 식별하는 것을 이용하는 것 등을 이용한다. 그러나, 우리는 당신이 설계하는 프로토콜들 안에서 이 방법을 사용하지 말기를 원한다. 우리는 같은 파일시스템을 사용하는 다른 기기로부터의 연결들을 허락해야 할지도 모르기 때문이다. 대신에, 만약 그것을 가지는 것을 원한다면, 각 클라이언트에게 식별번호를 보낸다. 파일 이름공간안의 소켓을 닫은 후에, 당신은 파일시스템으로부터 파일이름을 지워야 한다. unlink나 remove를 사용하여 이것을 하라. 9. 5절 [파일 삭제하기] 을 보라. 파일 이름공간은 단지 어떤 통신 스타일에 대해 하나의 프로토콜만 지원한다. 그것은 프로토콜 번호 0이다. 파일 이름 공간에 소켓을 만들려면, socket또는 sockerpair의 이름공간 인수에 상수 PF_FILE을 사용하라. 이 상수는 'sys/socket. h'에 정의되어 있다. int PF__FILE Macro
int PF__UNIX Macro
struct sockaddr__un Data Type
short int sun_family
char sun_path[108]
당신은 sun_family요소의 크기와 파일이름문자열의 (할당 크기가 아닌)문자열 길이의 합인, 파일이름공간에 소켓주소를 위한 길이 매개변수를 계산해야 한다. 여기 있는 것은 파일이름공간의 소켓을 만들고 이름지어주는 방법을 보여주는 예이다.
이 장에서는 프로토콜과 소켓이 인터넷 이름공간에서 사용되는 이름짓는 방법에 대해 서술한다. 인터넷 이름공간에서 소켓을 만들려면, socket이나 socketpair의 이름 공간인수로 이 이름공간의 PF_INET 기호를 사용한다. 이 매크로는 'sys/socket. h'에 정의되어 있다. int PF__INET Macro
인터넷 이름공간의 소켓 주소는 다음과 같은 성분을 포함한다: 당신이 연결하기 원하는 장치의 주소. 인터넷 주소는 몇 가지 방법으로 표현될 수 있다. 이러한 방법들은 11. 5. 1절 [호스트 주소] 와 11. 5. 2. 4절 [호스트 이름] 에서 논의한다. 그 장치의 포트 번호. 11. 5. 3절 [포트] 을 보라 당신은 주소와 포트번호가 네트워크 바이트 순서라고 불리는 정규화 된 포맷으로 표현된다는 것을 알아야 한다. 이에 관한 정보는 11. 5. 5절 [바이트 순서] 을 보라 인터넷 이름공간에서, 소켓주소는 호스트의 주소와 그 호스트의 포트를 포함한다. 추가적으로 당신이 선택한 프로토콜은 주소의 일부분처럼 효과적으로 제공된다. 왜냐하면 지역적인 포트번호는 특정한 프로토콜 안에서 의미를 가지기 때문이다. 인터넷 이름공간안의 소켓 주소의 표현에 관한 자료형은 'netinet/in. h' 헤더파일에 정의되어 있다. struct sockaddr__in Data Type
short int sin_family
struct in_addr sin_addr
unsigned short int sin_port
당신이 bind나 setsockname을 호출할 때, 만약 당신이 인터넷 이름공간 소켓 주소를 사용한다면, '길이' 매개변수로 sizeof (struct sockaddr_in)을 명시해야 한다. 인터넷의 각 컴퓨터는 하나 또는 그 이상의 인터넷 주소를 가진다. 주소는 인터넷의 모든 것들 사이에서 그 컴퓨터를 지시하는 숫자이다. 사용자는 통상 숫자로된 호스트 주소를 사용한다. 그것은 '128. 52. 46. 32'처럼 네 숫자로 되어 있고 점으로 나뉘어져 있다. 각 컴퓨터는 또한 하나 또는 그 이상의 호스트 이름을 가진다. 그것은 'churchy. gnu. ai. mit. edu'처럼 점으로 나뉘어진 단어의 문자열이다. 사용자가 호스트를 명시하게 하는 프로그램은 전형적으로 숫자주소와 호스트 이름 모두를 수용한다. 그러나 프로그램은 연결을 위해 숫자로된 주소를 필요로 한다. 즉 호스트 주소를 사용하기 위해, 당신은 그것이 상징하고 있는 숫자 주소로 변환해야 한다. 인터넷 호스트 주소는 데이터의 4바이트를 포함하는 숫자이다. 그것들은 두부분으로 나뉘는데, 네트워크 번호와 그 네크워크내의 지역 네트워크 주소 번호가 그것이다. 네트워크 숫자는 처음 하나, 둘 또는 세 개의 바이트를 포함한다. 나머지 바이트는 지역 주소이다. 네트워크 번호들은 네트워크 정보 센터 (NIC, Network Information Center)에 등록되어 있다. 그것들은 세 개의 클래스 A, B, C로 분할된다. 각각 컴퓨터마다의 지역네트워크 주소는 각 네트워크의 관리자에 의해 등록되어 있다. 클래스 A 네트워크는 0에서 127범위의 한 바이트 숫자를 가진다. 클래스 A 네트워크의 수는 매우 작지만, 각각은 굉장히 많은 수의 호스트를 지원한다. 중간크기의 클래스 B 네트워크는 두바이트의 네트워크 번호를 가진다. 첫 번째 바이트의 범위는 128에서 191까지이다. 클래스 C 네트워크는 가장 작다. 그것들은 세 바이트의 네트워크 번호를 가지며, 첫 번째 바이트의 범위는 192에서 255까지이다. 그러므로, 인터넷 주소의 처음 1, 2, 3바이트는 네트워크를 명시하는 것이다. 인터넷 주소의 나머지 바이트는 네트워크 안에서의 주소를 명시한다. 클래스 A네트워크 0은 모든 네트워크에 브로드캐스트용으로 예약되어 있다. 추가적으로 각 네트워크 내에서의 호스트 번호가 0인 것은 그 네트워크 내의 모든 호스트들에게 방송(broadcast)하기 위해 예약되어 있다. 클래스 A 네트워크 127은 루프백(loopback)용으로 예약되어 있다. 당신은 그러므로 인터넷 주소 '127. 0. 0. 1'을 사용하면 자신의 호스트장치를 참조 할 수 있다. 단일 장치는 여러 개의 네트워크의 멤버가 될 수 있으므로, 그것은 여러 개의 호스트 주소를 가질 수 있다. 그러나, 같은 호스트 주소를 가진 장치가 하나 이상 있어서는 안 된다. 인터넷 주소를 위한 숫자와 이름 표현은 네 가지 형태가 있다.
주소의 각부분에서, 기수를 표시하기 위해 보통 C관례를 사용한다. 다른 말로 하면, '0x' 또는 '0X'로 시작하는 것은 16진수 기수를 내포한다. '0'으로 시작하는 것은 8진수를 내포하고, 다른 것은 10진수 기수로 가정한다. 인터넷 호스트 주소는 정수 형들(unsigned long int형)같은 형식으로 표현된다. 다른 말로 하면, 정수들은 struct in_addr의 형태의 구조체 안에 들어가게 된다. 만약 용법이 일치되면 좋을 것이나, 그렇지 못하다면, 구조체로부터 정수를 뽑아 내거나, 정수를 구조체에 넣는 것이 쉽지 않을 것이다. 다음 인터넷 주소에 관한 기본적인 정의는 'netinet/in. h'헤더 파일 안에서 볼 수 있다: struct in_addr 자료형
unsigned long int INADDR__LOOPBACK Macro
unsigned long int INADDR__ANY Macro
unsigned long int INADDR__BROADCAST Macro
unsigned long int INADDR__NONE Macro
인터넷 주소를 조작하는 추가적인 함수들은 'arpa/inet. h'안에 선언되어 있다. 그것들은 네트워크 바이트 순서로 인터넷 주소를 표현한다. 즉 그것들은 네트워크 번호와 네트워크 안에서의 지역 주소를 호스트 바이트 순서로 표현한다. 네트워크와 호스트 바이트 순서에 관한 설명은 11. 5. 3절 [바이트 순서] 을 보라. int inet__aton (const char *name, struct in_addr *addr) 함수
unsigned long int inet__addr (const char *name) 함수
unsigned long int inet__network (const char *name) 함수
char * inet__ntoa (struct in_addr addr) 함수
struct in_addr inet__makeaddr (int net, int local) 함수
int inet__lnaof (struct in_addr addr) 함수
int inet__netof (struct in_addr addr) Function
인터넷 주소를 위한 숫자와 점으로 표현하는 것 외에, 당신은 의미 있는 이름을 사용하여 호스트를 참조할 수 있다. 의미 있는 이름을 사용하는 것의 장점은 역시 외우기 쉽다는 것이다. 예를 들어 인터넷 주소 '128. 52. 46. 32'를 가진 장치는 'churchy. gnu. ai. mit. edu'로도 표현된다. 또한 'gnu. ai. mit. edu' 도메인내의 다른 컴퓨터들은 간단하게 'churchy'로 이 장치를 참조할 수 있다. 내부적으로, 시스템은 호스트 이름과 호스트 번호 사이의 매핑의 정보를 유지하는 데이터베이스를 사용한다. 이 데이터베이스는 보통 '/etc/hosts'이거나 네임서버에 의해 제공된다. 이 데이터 베이스에 접근하기 위한 함수와 기호들은 'netdb. h'에 선언되어 있다. 만약 당신이 'netdb. h'를 포함한다면, 그것들은 무조건적으로 정의되어 있는 BSD들의 특징이다. struct hostent 자료형
char *h_name
char **h_aliases
int h_addrtype
int h_length
char **h_addr_list
char *h_addr
struct hostent * gethostbyname (const char *name) 함수
struct hostent * gethostbyaddr (const char *addr, int length, int format) 함수
extern int h_errno; 아래는 h_errno안에서 찾을 수 있는 error코드들이다: HOST_NOT_FOUND
TRY_AGAIN
NO_RECOVERY
NO_ADDRESS
void sethostent (int stayopen) 함수
struct hostent * gethostent () 함수
void endhostent () 함수
인터넷 이름공간에서의 소켓주소는, 장치의 인터넷 주소에 추가적으로 주어진 장치의 소켓을 구별하는 포트번호로 구성된다. 포트번호는 0에서 65535번까지의 범위이다. IPPORT_RESERVED보다 작은 포트번호는 표준서버에서 finger나 telnet과 같은 것을 위해 예약되어 있다. 시스템 내부에 이러한 것들을 유지하고 있는 데이터베이스가 있고, 당신은 getservbyname함수를 사용하여 서비스 이름과 포트번호의 맵을 만들 수 있다. ; 11. 5. 4절 [서비스 데이터베이스] 을 보라. 만약 데이터베이스 안에 정의된 표준 중의 하나가 아닌 서버를 작성하려면, 그것을 위한 포트번호를 선택해야 한다. IPPORT_USERRESERVED 보다 더 큰 숫자를 사용하라. 어떤 번호들은 서버들을 위해 예약되어 있고 시스템에 의해 자동으로 생성되지 않을 것이다. 다른 사용자들에 의한 서버사용과의 충돌을 피하는 것은 당신에게 달렸다. 당신이 그것의 주소를 명시하지 않고 소켓을 사용할 때, 시스템은 포트번호를 하나 생성한다. 이 번호는 IPPORT_RESERVED와 IPPORT_ USERRESERVED사이의 값이다. 인터넷에서, 같은 소켓주소(호스트 주소 + 포트주소)로 통신을 시도하지 않는다면, 같은 포트번호로 두 개의 다른 소켓을 가지는 것은 실제로 적당한 방법이다. 상위프로토콜이 그것을 요구할 때, 특별한 상황을 기대하고 같은 포트번호를 복사하지 말아라. 보통, 시스템은 그러한 일을 수행하지 않을 것이다. bind는 보통 다른 포트번호를 요구한다. 포트번호를 다시 사용하기 위해서는, 소켓옵션 SO_REUSEADDR를 세트하라. 11. 11. 2절 [소켓-수준 옵션]을 보라. 다음 매크로들은 'netinet/in. h'에 정의되어 있다. int IPPORT__RESERVED 매크로
int IPPORT__USERRESERVED 매크로
유명한 서비스의 경로를 유지하는 데이터베이스는 보통 '/etc/services'파일이거나 네임서버의 동등한 파일이다. 이 서비스 데이터베이스를 억세스하기 위해 'netdb. h'에 선언되어 있는 다음 유틸리티들을 사용할 수 있다. struct servent 자료형
char *s_name
char **s_aliases
int s_port
char *s_proto
특정한 서비스에 관한 정보를 얻으려면, getservbyname이나 getservby port 함수를 사용하라. 이 정보는 정적으로 할당된 구조체 안으로 반환된다. 즉 그것을 여러 번 호출하는 것으로부터 보호하려면 그 정보를 복사해 놓아야만 한다. struct servent * getservbyname (const char *name, const char *proto) 함수
struct servent * getservbyport (int port, const char *proto) 함수
void setservent (int stayopen) 함수
struct servent * getservent (void) 함수
void vndservent (void) 함수
컴퓨터의 종류가 틀리면, 한 워드 내에서 바이트의 순서가 틀리게 사용 될 수 있다. 어떤 컴퓨터들은 워드안에 상위 바이트가 먼저 오기도 하고 (이를 "큰 종결자(big-endian)"라 부른다), 다른 것들은 상위 바이트가 나중에 오기도 한다. (이를 "작은 종결자(little-endian)"라 한다) 다른 바이트 수를 사용하는 장치들이 통신하기 위해, 인터넷 프로토콜들은 네트워크 상에서 전송되는 데이터를 위해 규정된 바이트 수 명시하고 있다. 인터넷 소켓 연결을 설정할 때, 당신은 sockaddr_in구조체의 sin_port와 sin_addr멤버를 네트워크 바이트 수로 표현해야만 한다. 소켓을 통해 전송되는 정수 데이터를 코딩할 때 역시 그것을 네트워크 바이트 순서로 변환해야 한다. 만약 그렇게 하지 않는다면, 프로그램은 다른 종류의 장치와 통신을 하는데 실패할 것이다. 포트번호나 호스트 주소를 얻기 위해 getservbyname, gethostbyname, inet_addr를 사용한다면, 사용되는 값들은 이미 네트워크 바이트 순서로 되어 있는 것이다. 당신은 그것들을 sockaddr_in에 직접 복사할 수 있다. 그렇지 않은 경우, 값들을 정확히 변환하지 않으면 안 된다. sin_port멤버로 사용하기 위해 htons와 ntohs를 사용하여 값들을 변환하라. sin_addr멤버로 사용하기 위해 htonl과 ntohl를 사용하여 값들을 변환하라. (struct in_addr은 unsigned long int와 같은 것임을 기억하라) 이러한 함수들은 'netinet/in. h'안에 선언되어 있다. unsigned short inthtons (unsigned short int hostshort) 함수
unsigned short int ntohs (unsigned short int netshort) 함수
unsigned long int htonl (unsigned long int hostlong ) 함수
unsigned long int ntohl (unsigned long int netlong ) 함수
소켓에서 사용되는 통신 프로토콜은 어떻게 데이터를 교환할 것인가에 대한 저수준 세부사항을 제어한다. 예를 들면, 프로토콜은, 전송상의 에러검출을 위한 검사합계(checksum)같은 것이나, 메시지의 경로설정 명령 같은 것들을 구현한다. 일반 사용자 프로그램들은 이러한 세부사항들에 대해서 직접적인 영향을 받지는 않는다. 인터넷 이름공간의 기본 통신 프로토콜은 통신스타일에 의존한다. 스트림 통신의 기본 프로토콜은 TCP("전송 제어 프로토콜")이다. 데이터그램 통신의 기본 프로토콜은 UDP("유저 데이터그램 프로토콜")이다. 신뢰성 있는 데이터그램 통신의 기본 프로토콜은 RDP("신뢰성 있는 데이터그램 프로토콜")이다. 당신은 아마 거의 대부분 기본 프로토콜을 사용할 것이다. 인터넷 프로토콜은 일반적으로 숫자 대신 이름으로 명시된다. 호스트가 알고 있는 네트워크 프로토콜은 데이터베이스 안에 저장되어 있다. 이것은 보통 '/etc/protocols'파일 이에서 얻어지거나 , 네임서버에 의해 동등하게 제공될 수 있다. 당신은 getprotobyname함수를 사용하여 데이터베이스 내에서 프로토콜 이름에 연계된 프로토콜 번호를 찾아 낼 수 있다. 여기에 프로토콜 데이터베이스를 억세스하기 위한 유틸리티들의 자세한 정의가 있다. 이것들은 'netdb. h'에 선언되어 있다. struct protoent 자료형
char *p_name
char **p_aliases
int p_proto
구체적인 프로토콜에 관하여 프로토콜 데이터베이스를 검색하기 위해 getprotobyname과 getprotobynumber를 사용할 수 있다. 정적으로 할당된 구조체에 정보가 반환된다. 여러 번 호출되는 것으로부터 정보를 보호하기 위해 그것을 복사해야 놓아야 한다. struct protoent * getprotobyname (const char *name) 함수
struct protoent * getprotobynumber (int protocol) 함수
void setprotoent (int stayopen) 함수
struct protoent * getprotoent (void) 함수
void endprotoent (void) Function
여기에 인터넷 이름공간 안에 소켓을 만들고 이름짓는 방법을 보여주는 예제가 있다. 프로그램이 수행되는 장치에 새로 소켓이 만들어진다. 장치의 인터넷 주소를 찾고 사용하는 것 대신, 호스트 주소에는 INADDR_ANY를 명시하였다. 시스템은 장치의 실제주소로 그것을 대치한다.
다른 이름공간과 프로토콜패밀리들도 지원되지만 별로 사용되지 않으므로 아직 문서화되지 않았다. PF_NS는 Xerox 네트워크 소프트웨어 프로 콜에 관련된 것이다. PF_ISO 는 개방시스템상호연결(OSI)에 관련된 것이다. PF_CCITT는 CCITT의 프로토콜들에 관련된 것이다. 'socket. h'에 실제로 구현되지 않은 기호와 다른 이름의 프로토콜이 정의되어 있다. PF_IMPLINK는 호스트와 인터넷 메시지 처리기와의 통신에 사용된다. 이에 관한 정보와 가끔 사용되는 지역 경로설정 프로토콜인 PF_ROUTE에 관하여는 (미래에 나올) GNU Hurd Manual을 보라.
이 절에서는 소켓을 열고 다는 실제적인 라이브러리 함수에 관하여 서술한다. 모든 이름공간과 연결스타일에 대해 같은 함수가 사용된다. 소켓을 만들기 위해서는 'sys/socket. h'에 선언되어 있는 소켓함수를 사용한다. int socket (int namespace, int style, int protocol) 함수
EPROTONOSUPPORT
EMFILE : 프로세스가 이미 너무 많은 파일서술자들을 열어 놓았다. ENFILE : 시스템이 이미 너무 많은 파일서술자들을 열어 놓았다. EACCESS : 프로세스가 명시된 style이나 protocol에 맞는 소켓을 만들 권한을 갖고 있지 않다. ENOBUFS : 시스템 내부 버퍼 공간이 부족하다. socket 함수에 의해 반환되는 파일서술자는 읽기와 쓰기 기능 모두를 지원한다. 그러나 파이프 같은 소켓들은 파일 위치에 관한 동작은 하지 못한다. socket함수를 어떻게 호출하는 지에 대한 예는 11. 4절 [파일 이름공간], 또는 11. 5. 7절 [Inet 예제]을 보라. 소켓의 사용이 끝나면, 간단히 그 파일서술자를 close함수를 이용해 닫으면 된다. 8. 1절 [파일 열고 닫기]을 보라. 만약 연결을 통하여 전송되기를 기다리는 데이터가 여전히 있으면, 보통 close는 이 전송이 완료되도록 시도한다. SO_LINGER소켓 옵션을 사용하여 시간제한 주기를 명시해 주면, 이 과정을 제어할 수 있다. 11. 11절 [소켓 옵션] 을 보라. 당신은 'sys/socket. h'에 서술되어 있는 shutdown을 호출하므로 써 연결하의 송신만 또는 수신만을 종료시킬 수 있다. int shutdown (int socket, int how ) 함수
소켓 쌍은 연결된 (그러나 이름없는) 소켓의 쌍으로 구성된다. 그것은 pipe와 유사하고 무척 같은 방법으로 사용된다. 소켓 쌍은 'sys/socket. h'에 선언된 socketpair함수로 만들어진다. 소켓 쌍은 파이프와 대단히 유사하다: 주된 차이점은 소켓 쌍은 양방향이라는 것이다. 파이프는 하나의 입력만 되는 쪽과 출력만 되는 한 쪽만을 가지고 있다. (10장[Pipe와 FIFO]를 보라 ) int socketpair (int namespace, int style, int protocol, int filedes[2]) 함수
EMFILE : 프로세스가 너무 많은 파일 서술자를 열어 놓고 있다. EAFNOSUPPORT : 명시된 이름공간이 지원되지 않는 것이다. EPROTONOSUPPORT : 명시된 프로토콜이 지원되지 않는 것이다. EOPNOTSUPP 명시된 : 프로토콜이 소켓 쌍을 만드는 것을 지원하지 않는다.
대부분의 통신 스타일은 특정한 다른 소켓과 연결을 만들고 소켓과 소켓을 통하여 데이터를 교환한다. 연결을 만드는 것은 비대칭이다. ; 한쪽(클라이언트)은 다른 쪽(서버)이 소켓을 만들고 연결요구를 기다릴 때까지 연결을 요구하도록 되어 있다. 11. 8. 1절 [연결하기] 은 클라이언트 프로그램이 서버와 연결을 초기화하기 위해 무엇을 해야 하는지를 서술한다. 11. 8. 2절 [듣기] 과 11. 8. 3[연결을 수락하기] 에서는 서버 프로그램이 클라이언트로부터 연결요구를 기다리고 받아들이는 것에 대한 서술을 한다. 11. 8. 5[데이터전송]은 어떻게 연결된 소켓을 통하여 데이터를 전송하는 방법을 서술한다. 연결을 만들 때, 클라이언트는 서버가 연결을 기다리고 수락하는 동안 연결을 만들어야 한다. 여기에 클라이언트가 'sys/socket. h'에 선언된 connect함수를 이용하여 무엇을 해야 할 것인지를 논의하고 있다. int connect (int socket, struct sockaddr *addr, size_t length) 함수
EBADF : 소켓socket이 유효한 파일 서술자가 아니다. ENOTSOCK : 소켓socket이 소켓이 아니다. EADDRNOTAVAIL : 명시된 주소가 원격장치(상대방기기)에 사용할 수 없는 것이다. EAFNOSUPPORT : addr의 이름공간이 이 소켓에서 지원하지 않는 것이다. EISCONN : 소켓socket이 이미 연결되어 있다. ETIMEDOUT : 연결설정을 시도하다가 시간을 초과하였다. ECONNREFUSED : 서버가 연결설정을 직접 거절하였다. ENETUNREACH : 주어진 addr의 네트워크는 이 호스트로부터 도달할 수 없다. EADDRINUSE : 주어진 addr의 소켓주소가 이미 사용 중이다. EINPROGRESS : 소켓socket이 블록 킹되지 않는 것이고, 연결을 즉시 설정할 수 없었다. EALREADY : 소켓socket이 블록 킹되지 않는 것이고, 이미 진행중인 미결정의 연결이 있다. 이제 서버프로세스가 소켓에서 연결을 수락하기 위해 무엇을 해야 하는지 고려해보자. 이것은 listen함수를 사용하여 소켓에서 연결요구를 가능하게 하고 나서, accept함수 (11. 8. 3절 [연결수락]을 보라)를 사용하여 요구를 받아들이는 것을 포함한다. listen함수는 비연결 통신 스타일을 지원하지 않는다. 연결 요구가 있을 때까지 수행을 시작하지 않도록 네트워크 서버를 작성할 수 있다. 11. 10. 1절[Inetd 서버들]을 보라. 인터넷 이름공간에서, 한 포트로의 연결에 접근을 제어하는 보호 메커니즘이 없다. 어떤 장치에서 어떤 프로세스가 당신의 서버에 연결을 만들 수 있다. 만약 당신이 당신의 서버에 접근을 제어하기를 원한다면, 연결요구에 연계된 주소를 검사하거나, 다른 협상과정이나 식별기능이 있는 프로토콜을 구현하면 된다. 파일 이름공간에서, 보통 파일 보호 비트는 소켓 연결에 접근하는 사람을 제어할 수 있다. int listen (int socket, unsigned int n) 함수
EBADF : 인수socket는 유효한 파일서술자가 아니다. ENOTSOCK : 인수socket이 소켓이 아니다. EOPNOTSUPP : 소켓socket는 이 기능을 지원하지 않는다. 서버가 연결요구를 수신하였을 때, 연결요구를 수락함으로써 연결이 끝날 수 있다. accept함수를 사용하여 그것을 수행한다. 서버로 설정된 소켓은 여러 클라이언트로부터의 연결요구를 수락할 수 있다. 서버의 원 소켓(original socket)은 연결의 부분이 되지 않는다. 대신에, accept는 연결에 특정한 새로운 소켓을 만든다. accpect는 이 소켓에 대한 서술자를 반환한다. 서버의 원 소켓은 다음 연결요구를 듣기 위하여 계속 남아있다. 서버소켓의 비결된 연결요구의 수는 제한되어 있다. 만약 클라이언트들로 부터의 연결 요구가 서버가 그것을 처리할 수 있는 거 보다 더 빠르다면, 큐가 가득 채워 질 것이고, 추가적인 요구는 ECONNREFUSED에러로 거절된다. 비록 시스템 내부의 큐가 제한되어 있을 지라도 listen함수의 인수로 이 큐의 최대 길이를 명시할 수 있다. int accept (int socket, struct sockaddr *addr, size_t *length_ptr) 함수
EBADF : socket인수가 유효한 파일서술자가 아니다. ENOTSOCK : 서술자 socket인수가 소켓이 아니다. EOPNOTSUPP : 서술자 socket이 이 기능을 지원하지 않는다. EWOULDBLOCK : socket이 블록킹안되는 모드로 세트되어 있고, 즉시 연결될 수 있는 미결의 연결이 없다. accept함수는 비연결성 통신 스타일의 소켓에는 사용될 수 없다. int getpeername (int socket, struct sockaddr *addr, size_t *length_ptr) 함수
EBADF : socket인수가 유효한 파일 서술자가 아니다. ENOTSOCK : socket서술자가 소켓이 아니다. ENOTCONN : socket소켓이 연결되어 있지 않다. ENOBUFS : 충분한 내부 버퍼가 없다. 일단 소켓이 상대측과 연결이 되면, 데이터를 전송하는 일반적인 write와 read 동작을 수행할 수 있다. (8. 2절 [I/O 추상]을 보라) 소켓은 양방향 채널이므로 한쪽에서 읽고 쓰기가 가능하다. 소켓의 동작을 명시하는 몇 가지 I/O모드가 있다. 그러한 모드를 명시하려면, 더 일반적인 read와 write대신에 recv와 send 함수를 사용해야 한다. recv와 send함수는 특별한 I/O모드를 제어하기 위한 여러 가지 플랙을 명시하는데 사용되는 추가적인 인수를 필요로 한다. 예를 들어 out-of-band 데이터를 읽거나 쓰기 위하여 MSG_OOB플랙을 명시할 수 있고, 입력을 엿보기 위하여 MSG_PEEK를 세트하거나, 출력시 라우팅정보의 포함을 제어하기 위하여 MSG_DONTROUTE플랙을 명시할 수 있다. send함수는 'sys/socket. h'에 선언되어 있다. 만약 flag인수를 0으로 하는 경우면, send대신에 write를 쓸 수 있다. 8. 2절 [I/O 추상]을 보라. 만약 소켓이 연결되어 있는 상태라면, send나 write를 사용할 때 SIGPIPE라는 시그널을 얻을 것이다. (21. 2. 6절 [여러 가지 시그널]을 보라) int send (int socket, void *buffer, size_t size, int flags) 함수
EBADF : socket인수가 유효한 파일 서술자가 아니다. EINTR
ENOTSOCK : socket서술자가 소켓이 아니다. EMSGSIZE : 소켓종류가 메시지를 작게 보낼 것을 요구하는데, 이 메시지가 너무 크다. EWOULDBLOCK
ENOBUFS : 충분한 내부버퍼공간이 없다. ENOTCONN : 당신은 이 소켓에 연결되어 있지 않다. EPIPE
recv함수는 'sys/socket. h' 헤더 파일에 선언되어 있다. 만약 flags인수가 0이면 recv대신에 read를 써도 된다. 8. 2절 [I/O추상] 을 참조하라. int recv (int socket, void *buffer, size_t size, int flags) 함수
EBADF : socket인수가 유효한 파일서술자가 아니다. ENOTSOCK : socket서술자가 소켓이 아니다. EWOULDBLOCK
EINTR
ENOTCONN : 당신은 이 소켓에 연결되어 있지 않다. send와 recv에 사용되는 flags인수는 비트마스크이다. 당신은 이 인수에 값을 얻기 위해 아래 매크로로 비트별-OR연산을 수행할 수 있다. 'sys/socket. h'헤더파일에 모두 정의되어 있다. int MSG__OOB 매크로
int MSG__PEEK 매크로
int MSG__DONTROUTE 매크로
이것은 인터넷 이름공간의 byte stream을 위한 연결을 만드는 프로그램의 예제이다. 한 번 서버에 연결하고 특별한 일을 하지 않는다. 그것은 단지 텍스트 문자열을 서버에게 보내고 종료한다.
서버 쪽은 좀더 복잡하다. 여러 클라이언트가 동시에 서버에 연결할 수 있도록 하기를 원하므로, 간단히 하나의 read나 recv를 호출하여 하나의 클라이언트로부터 입력을 기다려서는 안 된다. 대신에, 모든 열린 소켓으로부터 입력을 기다리도록(8. 6절 [I/O 기다리기]), select를 사용하는 것이 올바른 것이다. 이것은 또한 추가적인 연결 요구를 다루도록 허락한다. 이 특별한 서버는 클라이언트로부터 메시지를 한 번 받는 다는 것 외에 특별히 흥미로운 일을 하지 않는다. 그것은 (클라이언트가 연결을 종료하는 결과로써) 파일의 끝(end-of-file)조건을 검출하였을 때, 그 클라이언트에 대한 소켓을 닫는다. 이 프로그램은 소켓주소를 세트하기 위해 make_socket과 init_sockaddr를 사용하였다. ; 11. 5. 7 [Inet 예제]을 보라
연결을 가진 스트림은 일반 데이터보다 높은 우선 순위로 배달되는 데이터인 out-of-Band데이터를 가능하게 한다. 전형적으로 out-of-band데이터를 전송하는 이유는 예외적인 상황의 통보 때문이다. out-of-band데이터를 보내는 방법은 MSG_OOB플랙을 세트한 (11. 8. 5. 1절[데이터 전송]참고) send를 사용하는 것이다. 수신 프로세스가 순서대로 그것을 받지 않으므로, out-of-band 데이터는 더 높은 우선 순위로 받아진다. 즉, 다음 가능한 out-of-band 데이터를 읽으려면, MSG_OOB플랙을 세트하여 recv를 사용한다. (11. 8. 5. 2절 [데이터 수신]을 보라). 보통 읽기 명령은 out-of-band데이터를 읽지 않는다. 그것들은 단지 일반 데이터만 읽는다. 소켓이 out-of-band데이터가 있음을 알게 되면, 소유프로세스나 소켓의 프로세스 그룹에 SIGURG시그널을 보낸다. F_SETOWN명령으로 fcntl함수를 사용하여 소유자를 명시할 수 있다. 8. 12절 [인터럽트 입력]을 보라. 또한 이 시그널의 핸들러를 설정할 수 있는데, out-of-band데이터를 읽는 등의 적절한 동작을 취하기 위해, 21장[시그널 핸들링]을 보라. 다른 것으로, select함수를 사용하여, 미결의 out-of-data를 검사하거나 out-of-band데이터가 있을 때까지 기다릴 수 있다. ; 그것은 소켓 예외 조건을 기다릴 수 있다. select에 관한 많은 정보는 8. 6절 [I/O를 기다리기]을 보라. (SIGURG를 사용하거나 select를 사용할 것이던지) out-of-band 데이터의 통고는 out-of-band데이터가 진행 중에 있음을 가리킨다. ; 즉 데이터는 아직 실제로 도착하지 않았다. 만약 그것이 완전히 도착하기 전에 out-of-data를 읽으려고 하면, recv 는 EWOULDBLOCK에러로 실패하게 된다. out-of-band데이터 전송은 자동으로 일반 데이터의 흐름 안에 "마크"를 둔다. 그것은 어디에 out-of-band데이터가 어디에 있을지를 보여준다. out-of-band 데이터가 먼저 보내진 모든 것들을 취소시킨다는 의미를 가질 때 유용하다. 여기에 수신 프로세스에서 마크전에 보내진 보통 데이터인지 아닌지 어떻게 테스트하는지가 나와있다. success = ioctl (socket, SIOCATMARK, &result);
만약 마크앞의 일반 데이터를 무시하지 않으려면, 그것을 어떻게든 읽기 위해, out-of-band데이터를 위한 내부시스템버퍼 공간을 만들어야 한다. 만약 out-of-band데이터를 읽으려 하는데 EWOULDBLOCK에러를 받는다면, 약간의 일반데이터를 (그것을 얻었을 때 사용할 수 있도록 저장을 하며) 읽기를 시도하라. 그리고 그것이 공간을 만드는지를 보아라. 여기 예제가 있다.
이번 절에서는 어떻게 연결 없는 통신스타일(SOCK_DGRAM과 SOCK_RDM스타일)을 사용하는지에 대해 서술한다. 이러한 스타일을 사용하여 패킷 안에 데이터를 묶어 넣고, 각 패킷은 독립적인 통신을 하게 된다. 그리고 각 패킷마다 목적지를 명시해야 한다. 데이터그램 패킷은 편지와 같다. 당신은 개별적으로 하나씩 목적지를 명시하여 보낸다. 그것들은 순서가 바뀌어 도착할 수도 있다. listen과 accept함수는 비연결 통신 스타일을 사용하는 소켓에서 사용할 수 없다. 데이터그램소켓으로 데이터를 보내는 보통 방법은 'sys/socket. h'에 선언되어 있는 sendto함수를 사용하는 것이다. 데이터그램 소켓에 connect를 호출할 수 있지만, 나중에 데이터전송을 위해 기본경로를 한 번 명시한다. 소켓이 기본경로를 가지면, send를 사용할 수 있다. (11. 8. 5. 1절 [데이터 전송]을 보라) 또한 패킷을 전송하기 위해 write를 사용할 수 있다. (8. 2절 [I/O 추상] 을 보라) addr인수에 AF_UNSPEC의 주소포맷을 사용하여 connect를 호출함으로써 기본경로를 취소할 수 있다. connect함수에 관한 더 많은 정보는 11. 8. 1절 [연결하기] 을 보라. int sendto (int socket, void *buffer size_t size, int flags, struct sockaddr *addr, size_t length) 함수
recvfrom함수는 데이터그램 소켓으로부터 패킷을 읽고 또한 어디서부터 온 것인지 알려준다. 이 함수는 'sys/socket. h'에 선언되어 있다. int recvfrom(int socket, void *buffer, size_t size, int flags, struct sockaddr *addr, size_t *length_ptr)함수
여기에 파일이름공간의 데이터그램 스트림을 통해 메시지를 보내는 예제프로그램의 세트가 있다. 클라이언트와 서버프로그램들 모두가 소켓을 만들고 이름짓기 위하여, 11. 4절 [파일 이름공간]에 설명되어 있는 make_named_socket 함수를 사용한다. 먼저 여기 서버프로그램이 있다. 그것은 메시지가 도착할 때까지 계속 기다리고 메시지가 오면 다시 송신자에게 되돌려주는 것을 반복한다. 분명히 특별히 유용한 프로그램이 아니지만, 일반적인 아이디어를 보여준다.
여기 위에 있는 서버프로그램에 맞는 클라이언트 프로그램이 있다. 그것은 서버에게 데이터그램을 송신하고 나서 응답을 기다린다. 클라이언트를 위한 소켓에는 (서버와 같이) 주어진 이름을 가지고 있음을 주시하라. 그것은 서버가 메시지를 바로 클라이언트에게 되돌리게 한다. 소켓이 연계된 연결상태를 가지지 않기 때문에, 서버는 클라이언트의 이름을 참조하여 그렇게 할 수 있는 것이다.
데이터그램소켓 통신은 비신뢰성임을 명심하라. 이 예제에서, 메시지가 서버에 도달하지 못하거나 서버가 응답을 하지 않을 지라도, 클라이언트 프로그램은 막연히 기다린다. 만약 원한다면, 그것을 종료시키고 리셋 시키는 프로그램을 유저가 수행하여야 한다. 자동적인 해결법은 select(8. 6절 [I/O기다리기])를 사용하여 응답의 시간제한을 설정하여, 시간제한이 초과되면 메시지를 재 전송하거나 소켓을 끝내고 종료하는 것이다.
위에서 듣기를 하는 서버프로그램을 작성하는 법을 설명했다. 어떤 서버는 그것에 접속하기 위해 미리 수행되고 있어야 한다. 인터넷포트를 위한 서비스를 제공하는 다른 방법은 inetd 데몬 프로그램을 이용하여 듣기를 하도록 하는 것이다. inetd는 명시된 포트의 세트에서의 메시지를 (select를 사용하여) 기다리며 수행되는 프로그램이다. 그것이 메시지를 받았을 때, (만약 소켓스타일이 연결이 필요하면) 연결을 수락하고 나서, 해당 서버프로그램을 수행하도록 자식프로세스를 만들어 낸다. '/etc/inetd. conf'파일 내에 포트들과 프로그램들을 명시한다. inetd에 의해 수행되는 서버프로그램을 작성하는 것은 매우 간단하다. 누군가 해당 포트로 연결을 연결하려는 때마다, 새로운 서버 프로세스가 시작된다. 연결은 단지 이 순간에만 존재한다. 소켓은 서버프로세스에서 표준 입력 서술자와 표준 출력 서술자 (서술자 0과 1)처럼 된다. 가끔은 프로그램이 일반적인 I/O기능을 필요로 할 때도 있다. ; 실제로, 소켓에 대해 아무 것도 모르는 범용 필터 프로그램도 inetd에 의해 바이트 스트림 서버처럼 동작할 수 있다. 비연결성 통신 스타일의 서버에도 inetd를 사용할 수 있다. 연결이 필요 없으므로, 이러한 서버들을 위해 inetd는 연결을 수락하려는 시도를 하지 않는다. 그것은 바로 서술자 0으로부터 수신된 데이터그램패킷을 읽을 수 있는 서버프로그램을 시작한다. 서버프로그램은 한 요구를 다룰 수 있고 종료할 수 있다. 또는 더 이상의 도착이 없을 때까지 요구를 읽는 것을 계속하고 나서 종료할 수도 있다. inetd를 설정할 때, 위의 두 가지 기술 중 어떤 것을 사용할 것인지 명시해야 한다. '/etc/inetd. conf'파일은 inetd에게 들을 포트번호와 수행될 서버프로그램이 무엇인지 말해준다. 보통 이 파일의 각 요소는 한 줄씩이다. 그러나, 그것을 화이트스페이스로 시작하는 요소의 첫 번째 줄을 제외한 모든 줄로 나눌 수 있다. '#'로 시작하는 줄은 주석 문이다. 여기 '/etc/inetd. conf'안의 두 기본적인 요소가 있다.
한 요소는 다음 형식을 가진다.
서비스 부분은 이 프로그램이 어떤 서비스를 제공하는 지를 말한다. 그것은 '/etc/services'안에 서비스의 이름이 정의되어 있을 것이다. inetd는 이 요소를 위해 들을 어떤 포트를 사용할 것인가 결정하는데 서비스를 사용한다. 스타일과 프로토콜 부분은 통신스타일과 소켓을 듣는데 사용되는 프로토콜을 명시한다. 스타일은 'SOCK_'이 빠지고, 소문자로 변환된 통신스타일의 이름이다. 예를 들면 stream 또는 dgram이다. 프로토콜은 '/etc/protocols'에 나열된 프로토콜 중 하나이다. 전형적인 프로토콜이름은 바이트 스트림 통신을 위한 'tcp'와 비신뢰성 데이터그램을 위한 'udp'가 있다. 대기 부분은 'wait' 또는 'nowait' 중 하나이다. 만약 통신스타일이 비연결성이고, 서버가 시작시에만 많은 다중 요구를 다룬다면 'wait'을 사용하라. 만약 inetd가 각 메시지나 요구가 들어 올 때마다 새로운 프로세스를 시작할 경우 'nowait'를 사용하라. 만약 스타일이 연결성이면 대기 부분은 'nowait'를 써라. 사용자명은 서버를 수행하는 사용자의 이름이다. inetd는 root로서 수행된다. 그래서 마음대로 그 자식의 사용자ID를 세트할 수 있다. 가능하면 사용자명에 'root'를 피하는 것이 좋다. ; 그러나 telnet과 ftp같은 어떤 서버는 사용자 이름과 암호를 읽는다. 이러한 서버들은, 네트워크로부터 오는 데이터에 의한 명령 같이 로그인 을 할 수 있도록 처음에 root가 될 필요가 있다. 프로그램 부분과 인수 부분은 서버를 시작할 때 수행되는 명령어를 명시한다. 프로그램은 수행 가능한 파일의 절대 경로의 파일이름이어야 한다. 인수는 화이트스페이스로 구분된 단어로 구성되어, 프로그램의 명령어라인 인수가 된다. 인수의 첫 번째 단어는 인수 0으로 (디렉토리 없이) 프로그램의 이름 그 자체로 된다. 만약 '/etc/inetd. conf'를 수정하면, inetd프로세스에게 SIGHUP신호를 inetd에게 파일을 다시 읽고, 새로운 내용을 얻게 하여야 한다. ps를 사용하여 inetd의 프로세스ID가 바뀌었는지 확인하면 된다.
이 장에서는 소켓의 행동과 그 밑에 있는 통신 프로토콜을 변경하는 여러 가지 옵션을 설정하고 읽는 방법을 서술한다. 소켓옵션을 다룰 때, 옵션이 속하는 레벨을 명시해 주어야 한다. 이것은 옵션이 소켓인터페이스에 적용되는 지, 저수준 통신 프로토콜 인터페이스에 적용되는 지를 서술한다. 여기에 소켓옵션을 변경하고 시험하는 함수가 있다. 'sys/socket. h'안에 그것들이 선언되어 있다. int getsockopt (int socket, int level, int optname, void *optval, size_t *optlen_ptr) 함수
EBADF : socket인수가 유효한 파일 서술자가 아니다. ENOTSOCK : 서술자 socket이 소켓이 아니다. ENOPROTOOPT : optname이 주어진 레벨에 맞지 않다. int setsockopt (int socket, int level, int optname, void *optval, size_t optlen) 함수
int SOL__SOCKET 상수
SO_DEBUG
SO_REUSEADDR
SO_KEEPALIVE
SO_DONTROUTE
SO_LINGER
struct linger 자료형
SO_BROADCAST
SO_OOBINLINE
SO_SNDBUF
SO_RCVBUF
SO_STYLE, SO_TYPE
SO_ERROR
많은 시스템은 시스템 개발자들에게 알려진 네트워크 리스트를 기록하는 데이터베이스를 가지고 있다. 이것은 보통 '/etc/networks' 또는 네임서버의 같은 파일을 유지한다. 이 데이터베이스는 route같은 라우팅 프로그램에서 유용하다. 그러나 네트워크를 통해 단순히 통신하는 프로그램에게는 별 필요가 없다. 우리는 'netdb. h'에 선언된 이 데이터베이스 접근 함수를 볼 것이다. struct netent 자료형
char *n_name
char **n_aliases
int n_addrtype
unsigned long int n_net
특정 네트워크에 관한 정보를 위해 네트워크 데이터베이스를 검색하기 위해 getnetbyname 또는 getnetbyaddr함수를 사용하라. 정보는 정적으로 할당된 구조체에 정보가 반환된다. ; 만약 그것을 저장할 필요가 있으면 그 정보를 복사해두어야 한다. struct netent * getnetbyname (const char *name) 함수
struct netent * getnetbyaddr (long net, int type) 함수
void setnetent (int stayopen) 함수
struct netent * getnetent (void) 함수
void endnetent (void) 함수
11. 1 소켓 개념
11. 2 통신스타일
11. 3 소켓 주소
11. 3. 1 주소 포맷
11. 3. 2 소켓의 주소를 세팅하기
11. 3. 3 소켓의 주소 읽기
11. 4 The File Namespace
11. 4. 1 파일 이름공간 개념들
11. 4. 2 파일이름 공간의 자세한 것
미완성: 왜 108이 매직넘버인가? RMS는 이것을 길이가 0인 배열을 만드는 것과 파일이름의 길이에 기초하여 적합한 저장공간을 할당하기 위해 allocate를 사용하는 것과 같은 예를 꼬집어 제안한다.
11. 4. 3 파일-이름공간 소켓의 예
11. 5 인터넷 이름공간
11. 5. 1 인터넷 소켓 주소 포맷
11. 5. 2 호스트 주소
11. 5. 2. 1 인터넷 호스트 주소
11. 5. 2. 2 호스트 주소 자료형
11. 5. 2. 3 호스트 주소 함수들
11. 5. 2. 4 호스트 이름들
11. 5. 3 인터넷 포트
11. 5. 4 서비스 데이터베이스
11. 5. 5 바이트 순서 변환
11. 5. 6 프로토콜 데이터베이스
11. 5. 7 인터넷 소켓 예제
11. 6 다름 이름공간들
11. 7 소켓 열고 닫기
11. 7. 1 소켓 만들기
11. 7. 2 소켓 닫기
11. 7. 3 소켓 쌍
11. 8 연결하는데 소켓사용
11. 8. 1 연결 만들기
11. 8. 2 연결 듣기
11. 8. 3 연결 수락
11. 8. 4 누가 나에게 연결되어 있나
11. 8. 5 데이터 전송
11. 8. 5. 1 데이터 보내기
11. 8. 5. 2 데이터 수신하기
11. 8. 5. 3 소켓 데이터 옵션
11. 8. 6 Byte Stream 소켓 예제
11. 8. 7 Byte Stream Connection 서버 예제
11. 8. 8 Out-of-Band 데이터
11. 9 데이터그램 소켓 명령
11. 9. 1 데이터그램 전송
11. 9. 2 데이터그램 수신
11. 9. 3 데이터그램 소켓 예제
11. 9. 4 데이터그램 읽기 예제
11. 10 inetd 데몬
11. 10. 1 inetd 서버들
11. 10. 2 inetd 설정
11. 11 소켓 옵션
11. 11. 1 소켓 옵션 함수
11. 11. 2 소켓-레벨 옵션
11. 12 네트워크 데이터베이스