공부 114

꼬리 재귀(Tail recursion)

재귀 함수가 반복문으로 짠 것 보다는 가독성이 좋지만 느릴 수 있다는 것은 이미 알고 있다. 하지만 이 재귀 함수의 단점을 어느 정도 커버할 수 있는 꼬리 재귀(Tail recursion)란 것이 있는데, 이것에 대해 간단히 정리해보자. 우선 꼬리 재귀란 재귀 함수이긴 하지만 재귀 함수 호출 이후에 연산을 추가적으로 하지 않는 재귀 함수 형태를 의미한다. 예를 들어서 factorial함수를 재귀 함수로 짜보면 int factorial(int Num) { if(Num == 0) return 1; return Num * factorial(Num - 1); } 아마 대부분 factorial함수를 재귀함수로 짤 때 이런식으로 만들 것이다. 하지만 보이다시피 factorial(Num - 1)을 호출하고 retur..

공부/그 외 2021.08.04

WINAPI 시작을 위한 필수 함수들

int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) 콘솔 프로그램에서 main처럼 WINAPI에서의 main(진입점)이라고 보면 된다. 여기서 APIENTRY는 __stdcall 함수 호출규약을 의미하는데 #define으로 정의되어 있다. #define CALLBACK __stdcall #define WINAPI __stdcall #define WINAPIV __cdecl #define APIENTRY WINAPI #define APIPRIVATE __stdcall #define PASCAL __stdcall WINAPI, APIENTR..

공부/WINAPI 2021.08.03

WINAPI 시작하기 - 초기 세팅

visual studio 2019에서 새 프로젝트 만들기 > windows 데스크톱 마법사 > 데스크톱 어플리케이션 & 빈 프로젝트로 생성 후 솔루션 하위에 있는 프로젝트 제거 > 프로젝트 파일이 존재하는 경로로 가서 Bin, include 폴더 생성 > 원래 존재하던 프로젝트 파일을 include에 모두 넣어주기 이렇게 하는 이유는 프로그래밍할 때 생기는 코드들은 모두 include에 넣어서 관리하고 결과적으로 만들어지는 실행파일들은 Bin폴더에 따로 보관하기 위해서 이렇게 세팅해준다. 그 후에 솔루션 우클릭 > 추가 > 기존 프로젝트 > 아까 include에 넣어준 프로젝트 열기 그리고 실행파일이 만들어지는 위치를 우리가 아까 만든 Bin폴더 안으로 설정해야 한다(기존에는 솔루션 명의 폴더 안에 De..

공부/WINAPI 2021.08.02

Linked list 구현

Linkedlist.h (템플릿으로 구현해서 헤더파일에 구현까지 넣음) #pragma once template class CNode { // 생성자, 소멸자를 privated으로 두고 CLinkedlist를 friend로 선언해서 // 외부에선 생성못하고 CLinkedlist만 생성할 수 있도록 함 private: CNode() {} ~CNode() {} private: template friend class CLinkedlist; template friend class CIterator; private: CNode* m_Next; CNode* m_Prev; T m_Data; }; template class CIterator { private: template friend class CLinkedlist..

소켓 옵션 정리

getsockopt & setsockopt 함수 이름에서부터 알 수 있듯이 socket의 옵션정보들을 얻거나 바꿀 수 있는 함수들이다. #include int getsocket(SOCKET sock, int level, int optname, char* optval, int* optlen) // 성공 시 0, 실패 시 SOCKET_ERROR 반환 sock : 옵션 정보를 얻을 소켓 level : 확인할 옵션의 프로토콜 레벨(ex. SOL_SOCKET, IPPROTO_IP, IPPROTO_TCP) optname : 확인할 옵션의 이름(ex. SO_RCVBUF, SO_SNDBUF, SO_TYPE 등) optval : 확인 결과 저장을 위한 버퍼의 주소값 optlen : optval이 가리키고 있는 타입의 크..

공부/Server 2021.08.01

도메인(Domain)과 DNS(Domain Name System)

서버들은 IP로 구분된다. 하지만 IP는 기억하기도 쉽지 않고 표현하기도 힘들다. 그래서 일종의 별명을 IP주소마다 부여했는데 이것을 도메인이라고 한다. 그리고 IP주소와 도메인 사이의 변환을 수행하는 시스템을 가리켜 DNS(Domain Name System)이라고 부른다. 실제로 우리가 특정 웹사이트에 접속할때는 주로 도메인을 이용해서 접속한다. 예를 들어서 검색창에 www.naver.com을 입력했다고 하자. 이때 DNS로 부터 해당 도메인의 IP정보를 얻어오는 과정은 아래와 같다. 1. 로컬 DNS 서버에 입력한 도메인을 IP주소로 변경해줄 것을 요청해서 접근한다. 모든 호스트에는 로컬 DNS 서버가 등록되어 있다. 2. 만약 이 로컬 DNS 서버에 내가 원하는 도메인의 IP주소가 없으면 Root ..

공부/Server 2021.08.01

TCP 기반의 소켓의 우아한 연결 종료(Half-close)

지금까지 TCP 종료 과정은 closesocket()으로 해왔다. 하지만 이 함수 호출은 완전 종료를 의미하며, 완전 종료는 입출력 스트림 모두를 종료한다는 의미이다. 참고로 두 호스트가 연결돼서 상호간의 송수신이 가능한 상태가 된다면 이걸 가리켜 '스트림이 형성된 상태'라고 한다. 이렇게 한쪽 호스트에서 일방적으로 스트림을 끊으면 반대 호스트에서 전송해야할 데이터를 수신 받지 못하게 된다. 연결을 종료했는데 왜 반대쪽에서 보내는 데이터를 또 받으려고 하는가?와 같은 의문이 생길 수도 있다. 예를 들어, 서버와 클라이언트가 스트림이 형성됐다면 서버는 클라이언트에게 파일을 전송하고 서버가 모든 파일의 모든 내용을 전송했다면 끝이라는 의미로 EOF를 전송해야 한다고 해보자. 클라이언트는 서버로부터 EOF를 ..

공부/Server 2021.08.01

TCP/UDP에 대한 이해

인터넷 프로토콜 기반 소켓의 경우 데이터 전송 방법에 따라 TCP(Transmission Control Protocol)/UDP(User Datagram Protocol)로 나뉜다. TCP/UDP는 TCP/IP 프로토콜 스택에 속해 있다. TCP/IP 프로토콜 스택은 4개의 계층으로 나뉘어 있는데 이를 통해 데이터 송수신 과정을 4개의 영역으로 나누어 구현했다는 것을 알 수 있다. 만약 TCP소켓을 생성해서 데이터를 송수신한다면 아래 그림에 있는 4개의 계층을 통해서 이루어 질 것이다. UDP소켓을 생성해서 데이터를 송수신한다면 아래 그림에 있는 계층들을 통할 것이다. 각 계층에 대해 먼저 알아보자. LINK 계층 LINK 계층은 물리적인 영역의 표준화에 대한 결과이다. LAN, WAN과 같은 네트워크 ..

공부/Server 2021.08.01

윈도우 기반 소켓 프로그래밍 필수 함수

// 성공 시 소켓 핸들, 실패시 INVALID_SOCKET 반환 #include SOCKET socket(int af, int type, int protocol) af : 프로토콜 체계 type : 소켓 타입 protocol : 호스트간 통신에 사용되는 프로토콜 // IP주소와 PORT번호 할당 // 성공 시 0, 실패 시 SOCKET_ERROR 반환 #include int bind(SOCKET s, const struct sockaddr* name, int namelen) s : socket함수로부터 할당 받은 소켓 핸들 name : IP주소, PORT번호를 할당한 sockaddr구조체 포인터. 보통 SOCKADDR_IN타입의 구조체에 IP주소와 PORT번호를 할당하고 SOCKADDR*로 형변환해서 ..

공부/Server 2021.07.31

C 입력 버퍼 비우기

C언어를 처음 공부하다보면 scanf로 입력을 받을 때 갑자기 입력을 안받고 넘어가버리는 경우가 있다. 예를 들어서 #include int main() { int num; char c; printf("숫자를 입력하세요 : "); scanf("%d", &num); printf("문자를 입력하세요 : "); scanf("%c", &c); return 0; } 이걸 실행하면 숫자만 입력받고 프로그램이 종료된다. 위의 경우 character를 입력받아야 할 부분에서 입력받지 않고 그냥 넘어가버리는 것을 확인할 수 있다. 숫자를 입력해야하는 부분을 문자열로 바꾸면 이번에는 문자열만 입력받고 character는 입력받지 않고 끝난다. #include int main() { char buf[30]; char c; p..

공부/C || C++ 2021.07.30