K 개발자
소켓 개설 본문
소켓 프로그래밍에서 첫 번째로 해야 할 일은 통신 창구 역할을 하는 소켓을 만드는 것이다.
이것은 서버와 클라이언트에서 모두 필요한데 이를 위하여 socket() 함수를 이용한다.
socket()이 성공적으로 수행되면 새로 만들어진 소켓번호를 리턴하고 에러가 발생하면 -1이 리턴되며 이때 전역변수 errno에 에러코드가 들어간다.
socket()의 사용 문법은 다음과 같다.
#include <sys/socket.h>
int socket(
int domain, // 프로토콜 체계
int type, // 서비스 타입
int protocol // 소켓에서 사용할 프로토콜
)
domain으로 지정할 수 있는 프로토콜 체계에는 다음과 같은 것이 있다.
- PF_INET (인터넷 프로토콜 체계 사용)
- PF_INET6 (IPv6 프로토콜 체계 사용)
- PF_UNIX (유닉스 방식의 프로토콜 체계 사용)
- PF_NS (XEROX 네트워크 시스템의 프로토콜 체계 사용)
- PF_PACKET (리눅스에서 패킷 캡쳐를 위해서 사용)
socket()의 두 번째 인자 type은 서비스 타입을 말하는데, TCP를 이용하려면 SOCK_STREAM을, UDP를 이용하려면 SOCK_DGRAM을 선택하여야 한다.
- SOCK_STREAM (TCP 소켓 생성)
- SOCK_DGRAM (UDP 소켓 생성)
- SOCK_RAW (RAW 소켓 생성)
socket()의 세 번째 인자 protocol은 이 소켓에서 어떤 프로토콜을 사용할지를 지정하는데 type에서 SOCK_STREAM이나 SOCK_DGRAM을 정한 경우에는 이미 프로토콜이 TCP나 UDP로 정해졌으므로 protocol 값은 사용되지 않으며 0을 입력하면 된다.
type에서 SOCK_RAW를 선택한 경우에는 protocol 필드가 구체적인 상위 프로토콜을 지정하는 데 사용된다.
open_socket.c
socket()을 호출하고 생성된 소켓번호를 출력하는 예제이다.
이 프로그램에서는 /etc/passwd 파일을 열고 리턴된 파일 디스크립터를 출력한 후, 소켓을 두 개 열어서 소켓번호가 어떤 값인지 확인한다.
다음에는 다른 파일(/etc/hosts)을 하나 더 열어서 파일 디스크립터를 출력한다.
#include <stdio.h> // 표준 라이브러리
#include <stdlib.h> // 표준 라이브러리
#include <sys/types.h> // 소켓 시스템 콜에 필요한 상수 선언
#include <sys/stat.h> // 파일의 상태에 대한 데이터 선언
#include <sys/socket.h> // 소켓 시스템 콜 선언
#include <fcntl.h> // open에 필요한 flag 선언
int main(void) {
// 파일 및 소켓번호
int fd1, fd2, sd1, sd2;
// 파일 열기
fd1 = open("/etc/passwd", O_RDONLY, 0);
printf("/etc/passwd's file descriptor = %d\n", fd1);
// 스트림형 소켓 열기
sd1 = socket(PF_INET, SOCK_STREAM, 0);
printf("stream socket descriptor = %d\n", sd1);
// 데이터그램형 소켓 열기
sd2 = socket(PF_INET, SOCK_DGRAM, 0);
printf("datagram socket descriptor = %d\n", sd2);
// 또 다른 파일 열기
fd2 = open("/etc/hosts", O_RDONLY, 0);
printf("/etc/host's file descriptor = %d\n", fd2);
// 파일 및 소켓 닫기
close(fd2);
close(fd1);
close(sd2);
close(sd1);
return 0;
}
실행 결과
파일을 open하여 얻는 파일 디스크립터가 3번부터 배정되는 이유는 시스템이 이미 0, 1, 2번 파일 디스크립터를 각각 표준 입력, 표준 출력, 그리고 표준 에러 출력으로 사용하기 때문이다.
'유닉스(Unix) > 네트워크 프로그래밍' 카테고리의 다른 글
TCP 에코 클라이언트 (0) | 2022.01.03 |
---|---|
daytime 클라이언트 (0) | 2022.01.03 |
도메인 주소 변환 (0) | 2021.12.28 |
IP 주소 변환 (0) | 2021.12.28 |
바이트 순서 (0) | 2021.12.26 |