1 | in_addr_t inet_addr(const char *cp); | cs |
1 2 3 4 5 6 7 8 | #ifndef __linux__ #include <WinSock2.h> //윈도우 환경일시 #else #include<sys/types.h> //리눅스 환경일시 #include<sys/socket.h> //리눅스 환경일시 #endif int socket(int domain, int type, int protocol); | cs |
domain - 네트워크에 따라 달라진다 TCP/IP 시 AF_INET
type - 소켓의 형태 SOCKET_STREAM , SOCK_DGRAM ,프로토콜 헤더를 직접 만들 경우 SOCK_RAW
RAW 소켓은 패킷은 만드는 것은 물론 송수신하는 네트워크 패킷의 데이터를 확인 할 수 있는데 리눅스에서는 root권한으로만 실행 가능하고 윈도우에서는 지원하지 않는다
prorocol - 소켓의 프로토콜 타입 지정 보통 0으로 지정하거나 맞는 프로토콜 값으로 지정
소켓 디스크립터 socket descriptor 란? socket이 성공적으로 생성되었으면 리턴되는 값으로 이로 각각의 소켓을 구분한다
#02 connect
1 2 3 4 5 6 7 8 | #ifndef __linux__ #include <WinSock2.h> //윈도우 환경일시 #else #include<sys/types.h> //리눅스 환경일시 #include<sys/socket.h> //리눅스 환경일시 #endif int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); | cs |
연결 대기 중인 서버로 실제 연결을 맺는 함수
sockfd - socket 함수가 리턴하는 소켓 디스크립터
addr - 접속하고자 하는 아이피 및 서버 포트 정보가 있는 sockaddr 구조체의 주소값
addrlen - 전달하고자 하는 구조체의 길이
1 2 3 4 | struct sockaddr { unsigned short sa_family; char sa_data[14]; }; | cs |
소켓 통신을 하는 컴퓨터에 대한 IP 주소를 저장하는 데 사용된다
sa_family - 어떤 주소 체계를 가지고 있는지를 나타낸다 예를 들어 IP주소 체계인지 유닉스 주소 체계인지
sa_data - 14바이트의 주소 정보가 기록 된다
소켓이란 IP/TCP 통신만을 위해 존재하는 게 아닌 모든 네트워크 통신을 지원하기 위해 만들어 졌기 때문에 sockaddr 구조체는 다른 구조체로 캐스팅 되어서 사용된다. 주로 사용하는 TCP/IP의 주소정보를 저장하기 위해서는 sockaddr_in의 구조체가 캐스팅 되어 사용된다
1 2 3 4 5 6 | struct sockaddr_in { short sin_family; //주소 체계 USHORT sin_port; // 포트 번호 IN_ADDR sin_addr; //ip 주소 CHAR sin_zero[8]; // 패딩 } | cs |
sockaddr(2바이트+14바이트) sockaddr_in(2+2+4+8) 사이즈가 같아서 캐스팅이 가능하다 char sin_zero[8]은 sockaddr 구조체와 크기를 맞추기 위한 것이다
in_addr 구조체는 다음과 같이 union으로 선언되어 있다
1 2 3 4 5 6 | typedef struct in_addr { union { struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b; struct { USHORT s_w1,s_w2; } S_un_w; ULONG S_addr; } S_un; | cs |
#03 bind
1 2 3 4 5 6 7 8 | #ifndef __linux__ #include <WinSock2.h> //윈도우 환경일시 #else #include<sys/types.h> //리눅스 환경일시 #include<sys/socket.h> //리눅스 환경일시 #endif int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); | cs |
sockfd - socket 함수가 리턴하는 소켓 디스크립터
addr - 접속하고자 하는 아이피 및 서버 포트 정보가 있는 sockaddr 구조체의 주소값
addrlen - 전달하고자 하는 구조체의 길이
connect 함수와 동일하지만 하는 역할은 다르다
클라이언트 측의 sockaddr_in 은 서버의 ip주소와 포트번호 지만 서버측의 즉 bind() 에서의 sockaddr_in 은 연결 받고자 하는 소켓번호와 소켓 주소이다
#04 listen
1 2 3 4 5 6 7 8 | #ifndef __linux__ #include <WinSock2.h> //윈도우 환경일시 #else #include<sys/types.h> //리눅스 환경일시 #include<sys/socket.h> //리눅스 환경일시 #endif int listen(int sockfd, int backlog); | cs |
연결을 기다리는 함수이다
sockfd - 소켓 디스크립터
backlog - 연결을 기다리는 대기열 큐의 사이즈
#05 accept
1 2 3 4 5 6 7 8 | #ifndef __linux__ #include <WinSock2.h> //윈도우 환경일시 #else #include<sys/types.h> //리눅스 환경일시 #include<sys/socket.h> //리눅스 환경일시 #endif int accept(int sockfd, struct sockaddr * addr, socklen_t * addrlen); | cs |
연결을 수락하는 함수
연결 성공 시 리턴 값은 연결을 받아들인 새로운 소켓 디스크립터이다 실패 시 -1 리턴
연결 요청이 없는 경우 요청이 있을 때까지 대기 상태를 유지한다
sockfd - 연결을 기다리는 소켓 디스크립터
addr - 받아들인 클라이언트 주소 및 포트 정보가 있는 sockaddr 구조체의 주소값
addrlen - sockaddr 구조체의 길이가 저장된 변수의 주소값
#05 send
1 2 3 4 5 6 7 8 | #ifndef __linux__ #include <WinSock2.h> //윈도우 환경일시 #else #include<sys/types.h> //리눅스 환경일시 #include<sys/socket.h> //리눅스 환경일시 #endif ssize_t send(int sockfd, const void *buf, size_t len, int flags); | cs |
1 2 3 4 5 6 7 8 | #ifndef __linux__ #include <WinSock2.h> //윈도우 환경일시 #else #include<sys/types.h> //리눅스 환경일시 #include<sys/socket.h> //리눅스 환경일시 #endif ssize_t recv(int sockfd, void *buf, size_t len, int flags); | cs |
#07 sendto
1 2 3 4 5 6 7 8 9 | #ifndef __linux__ #include <WinSock2.h> //윈도우 환경일시 #else #include<sys/types.h> //리눅스 환경일시 #include<sys/socket.h> //리눅스 환경일시 #endif ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); | cs |
데이터그램 기반 전송 함수
1 2 3 4 5 6 7 8 9 | #ifndef __linux__ #include <WinSock2.h> //윈도우 환경일시 #else #include<sys/types.h> //리눅스 환경일시 #include<sys/socket.h> //리눅스 환경일시 #endif ssize_t recvfrom(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *src_addr, socklen_t addrlen); | cs |
#09 close - 리눅스
1 2 | #include <unistd.h> int close(int fd); | cs |
파일을 닫을 때 사용하는 close 함수가 소켓 디스크립터를 닫을 떄도 close 함수를 사용 할 수 있다
#10 closesocket - 윈도우
1 2 | #include <WinSock2.h> int closesocket(_In_ SOCKET s); | cs |
윈도우 환경에서는 소켓 디스크립터를 닫을 때는 closesocket 함수를 이용해야 한다
#11 WSAStartup - 윈도우
1 2 | #include <WinSock2.h> int WSAStartup(WORD wVersionRequested, LPWSADATA IpWSAData); | cs |
윈도우에서는 소켓 라이브러리를 사용하기 때문에 소켓 라이브러리 버전을 명시해줘야한다
wVersionRequested - 버전 정보
IpWSAData - 소켓의 세부 정보
#12 WSACleanup - 윈도우
1 2 | #include <WinSock2.h> int WSACleanup(void); | cs |
소켓 라이브러리를 사용한 후 소켓 라이브러리를 해제 해줘야한다
WSAClenup 함수를 호출 시기는 프로그램이 종료하기 직전에 소켓 함수를 사용하지 않게 될 때 호출한다