글쓴이 글 목록: opener

[C++ 정리] 자료형의 크기 및 범위 2015-06-11

32비트를 기준으로 한 자료형의 크기 및 범위이다. 다른 OS(16비트, 64비트)나 컴파일러에서 자료형의 크기가 조금씩 다르다는점 기억해 두자.

구분 자료형 크기 범위
기본형 void
문자형 (signed) char 1 byte -128 ~ 127
unsigned char 1 byte 0 ~ 255
wchar_t 2 byte 0 ~ 65,535
정수형 bool 1 byte 0 ~ 1
(signed) short (int) 2 byte -32,768 ~ 32,767
unsigned short (int) 4 byte 0 ~ 65,535
(signed) int 4 byte -2,147,483,648 ~ 2,147,483,647
unsigned int 4 byte 0 ~ 4,294,967,295
(signed) long (int) 4 byte -2,147,483,648 ~ 2,147,483,647
unsigned long (int) 4 byte 0 ~ 4,294,967,295
__int8 1 byte -128 ~ 127
__int16 2 byte -32,768 ~ 32,767
__int32 4 byte -2,147,483,648 ~ 2,147,483,647
__int64 8 byte -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
실수형 float 4 byte 3.4E-38(-3.4*10^38) ~ 3.4E+38(3.4*10^38) (7digits)
(long) double 8 byte 1.79E-308(-1.79*10^308) ~ 1.79E+308(1.79*10^308) (15digits)

 

OS별(16bit/32bit/64bit) 크기 사용의 요점은 다음과 같다.
  * int는 시스템의 기본연산 단위를 사용한다. (16bit=>2byte, 32=>4byte, 64=>4byte)
  * 64bit에서 long형을 8byte로 확장하였다. (16bit=>4byte, 32=>4byte, 64=>8byte)

 

다음코드로 자료형의 크기를 확인할 수 있다.
#include "stdafx.h"
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	cout << "char \t\t: " << sizeof(char) << " bytes\n";
	cout << "unsigned char \t: " << sizeof(unsigned char) << " bytes\n";
	cout << "wchar_t \t: " << sizeof(wchar_t) << " bytes\n";
	cout << "bool \t\t: " << sizeof(bool) << " bytes\n";
	cout << "short \t\t: " << sizeof(short) << " bytes\n";
	cout << "unsigned short \t: " << sizeof(unsigned short) << " bytes\n";
	cout << "int \t\t: " << sizeof(int) << " bytes\n";
	cout << "unsigned int \t: " << sizeof(unsigned int) << " bytes\n";
	cout << "long  \t\t: " << sizeof(long) << " bytes\n";
	cout << "unsigned long \t: " << sizeof(unsigned long) << " bytes\n";
	cout << "__int8 \t\t: " << sizeof(__int8) << " bytes\n";
	cout << "__int16 \t: " << sizeof(__int16) << " bytes\n";
	cout << "__int32 \t: " << sizeof(__int32) << " bytes\n";
	cout << "__int64 \t: " << sizeof(__int64) << " bytes\n";
	cout << "float \t\t: " << sizeof(float) << " bytes\n";
	cout << "double \t\t: " << sizeof(double) << " bytes\n";
	return 0;
}

data_type

[C++ 정리] 변수명 정의 규칙 2015-06-10

* 중복된 변수이름은 사용할 수 없다
* 언더스코어(_)를 제외한 특수문자는 사용할 수 없다
* 숫자로 시작하는 변수명은 사용할 수 없다
* 변수명 길이에 제한은 없다
* 변수명은 대소문자를 구분하지만 프로그램시 혼동이 오므로 동일명은 사용하지 않도록한다.
* 키워드를 변수명으로 사용할 수 없다(키워드 목록)

[TCP/IP] 에코서버 & 클라이언트 – IOCP 2015-05-28

서버

/*
## 소켓 서버 : 1 v n - IOCP
1. socket()			: 소켓생성
2. bind()			: 소켓설정
3. listen()			: 수신대기열생성
4. accept()			: 연결대기
5. read()&write()
	WIN recv()&send	: 데이터 읽고쓰기
6. close()
	WIN closesocket	: 소켓종료
*/

#include "stdafx.h"
#include <winsock2.h>

#pragma comment(lib, "Ws2_32.lib")

#define MAX_BUFFER		1024
#define SERVER_PORT		3500

struct SOCKETINFO
{
	WSAOVERLAPPED overlapped;
	WSABUF dataBuffer;
	SOCKET socket;
	char messageBuffer[MAX_BUFFER];
	int receiveBytes;
	int sendBytes;
};

DWORD WINAPI makeThread(LPVOID hIOCP);

int _tmain(int argc, _TCHAR* argv[])
{
	// Winsock Start - windock.dll 로드
	WSADATA WSAData;
	if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
	{
		printf("Error - Can not load 'winsock.dll' file\n");
		return 1;
	}

	// 1. 소켓생성  
	SOCKET listenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
	if (listenSocket == INVALID_SOCKET)
	{
		printf("Error - Invalid socket\n");
		return 1;
	}

	// 서버정보 객체설정
	SOCKADDR_IN serverAddr;
	memset(&serverAddr, 0, sizeof(SOCKADDR_IN));
	serverAddr.sin_family = PF_INET;
	serverAddr.sin_port = htons(SERVER_PORT);
	serverAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

	// 2. 소켓설정
	if (bind(listenSocket, (struct sockaddr*)&serverAddr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
	{
		printf("Error - Fail bind\n");
		// 6. 소켓종료
		closesocket(listenSocket);
		// Winsock End
		WSACleanup();
		return 1;
	}

	// 3. 수신대기열생성
	if (listen(listenSocket, 5) == SOCKET_ERROR)
	{
		printf("Error - Fail listen\n");
		// 6. 소켓종료
		closesocket(listenSocket);
		// Winsock End
		WSACleanup();
		return 1;
	}

	// 완료결과를 처리하는 객체(CP : Completion Port) 생성
	HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);	

	// 워커스레드 생성
	// - CPU * 2개
	SYSTEM_INFO systemInfo;
	GetSystemInfo(&systemInfo);
	int threadCount = systemInfo.dwNumberOfProcessors * 2;
	unsigned long threadId;
	// - thread Handler 선언
	HANDLE *hThread = (HANDLE *)malloc(threadCount * sizeof(HANDLE));
	// - thread 생성
	for (int i = 0; i < threadCount; i++)
	{
		hThread[i] = CreateThread(NULL, 0, makeThread, &hIOCP, 0, &threadId);
	}

	SOCKADDR_IN clientAddr;
	int addrLen = sizeof(SOCKADDR_IN);
	memset(&clientAddr, 0, addrLen);
	SOCKET clientSocket;
	SOCKETINFO *socketInfo;
	DWORD receiveBytes;
	DWORD flags;
	
	while (1)
	{
		clientSocket = accept(listenSocket, (struct sockaddr *)&clientAddr, &addrLen);
		if (clientSocket == INVALID_SOCKET)
		{
			printf("Error - Accept Failure\n");
			return 1;
		}

		socketInfo = (struct SOCKETINFO *)malloc(sizeof(struct SOCKETINFO));
		memset((void *)socketInfo, 0x00, sizeof(struct SOCKETINFO));
		socketInfo->socket = clientSocket;
		socketInfo->receiveBytes = 0;
		socketInfo->sendBytes = 0;
		socketInfo->dataBuffer.len = MAX_BUFFER;
		socketInfo->dataBuffer.buf = socketInfo->messageBuffer;
		flags = 0;

		hIOCP = CreateIoCompletionPort((HANDLE)clientSocket, hIOCP, (DWORD)socketInfo, 0);

		// 중첩 소캣을 지정하고 완료시 실행될 함수를 넘겨준다.
		if (WSARecv(socketInfo->socket, &socketInfo->dataBuffer, 1, &receiveBytes, &flags, &(socketInfo->overlapped), NULL))
		{
			if (WSAGetLastError() != WSA_IO_PENDING)
			{
				printf("Error - IO pending Failure\n");
				return 1;
			}
		}
	}

	// 6-2. 리슨 소켓종료
	closesocket(listenSocket);

	// Winsock End
	WSACleanup();
	
	return 0;
}

DWORD WINAPI makeThread(LPVOID hIOCP)
{
	HANDLE threadHandler = *((HANDLE *)hIOCP);
	DWORD receiveBytes;
	DWORD sendBytes;
	DWORD completionKey;
	DWORD flags;
	struct SOCKETINFO *eventSocket;
	while (1)
	{
		// 입출력 완료 대기
		if (GetQueuedCompletionStatus(threadHandler, &receiveBytes, &completionKey, (LPOVERLAPPED *)&eventSocket, INFINITE) == 0)
		{
			printf("Error - GetQueuedCompletionStatus Failure\n");
			closesocket(eventSocket->socket);
			free(eventSocket);
			return 1;
		}

		eventSocket->dataBuffer.len = receiveBytes;
		
		if (receiveBytes == 0)
		{
			closesocket(eventSocket->socket);
			free(eventSocket);
			continue;
		}
		else
		{
			printf("TRACE - Receive message : %s (%d bytes)\n", eventSocket->dataBuffer.buf, eventSocket->dataBuffer.len);
			
			if (WSASend(eventSocket->socket, &(eventSocket->dataBuffer), 1, &sendBytes, 0, NULL, NULL) == SOCKET_ERROR)
			{
				if (WSAGetLastError() != WSA_IO_PENDING)
				{
					printf("Error - Fail WSASend(error_code : %d)\n", WSAGetLastError());
				}
			}

			printf("TRACE - Send message : %s (%d bytes)\n", eventSocket->dataBuffer.buf, eventSocket->dataBuffer.len);
						
			memset(eventSocket->messageBuffer, 0x00, MAX_BUFFER);
			eventSocket->receiveBytes = 0;
			eventSocket->sendBytes = 0;
			eventSocket->dataBuffer.len = MAX_BUFFER;
			eventSocket->dataBuffer.buf = eventSocket->messageBuffer;
			flags = 0;

			if (WSARecv(eventSocket->socket, &(eventSocket->dataBuffer), 1, &receiveBytes, &flags, &eventSocket->overlapped, NULL) == SOCKET_ERROR)
			{
				if (WSAGetLastError() != WSA_IO_PENDING)
				{
					printf("Error - Fail WSARecv(error_code : %d)\n", WSAGetLastError());
				}
			}				
		}		
	}
}

클라이언트

/*
## 소켓 서버 : 1 v n - IOCP
1. socket()			: 소켓생성
2. connect()		: 연결요청
3. read()&write()
	WIN recv()&send	: 데이터 읽고쓰기
4. close()
	WIN closesocket	: 소켓종료
*/

#include "stdafx.h"
#include <winsock2.h>

#pragma comment(lib, "Ws2_32.lib")

#define MAX_BUFFER		1024
#define SERVER_IP		"127.0.0.1"
#define SERVER_PORT		3500

struct SOCKETINFO
{	
	WSAOVERLAPPED overlapped;
	WSABUF dataBuffer;	
	int receiveBytes;
	int sendBytes;
};

int _tmain(int argc, _TCHAR* argv[])
{	
	// Winsock Start - winsock.dll 로드
	WSADATA WSAData;
	if (WSAStartup(MAKEWORD(2, 0), &WSAData) != 0)
	{
		printf("Error - Can not load 'winsock.dll' file\n");
		return 1;
	}

	// 1. 소켓생성
	SOCKET listenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
	if (listenSocket == INVALID_SOCKET)
	{
		printf("Error - Invalid socket\n");
		return 1;
	}

	// 서버정보 객체설정
	SOCKADDR_IN serverAddr;
	memset(&serverAddr, 0, sizeof(SOCKADDR_IN));
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_port = htons(SERVER_PORT);
	serverAddr.sin_addr.S_un.S_addr = inet_addr(SERVER_IP);

	// 2. 연결요청
	if (connect(listenSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
	{
		printf("Error - Fail to connect\n");
		// 4. 소켓종료
		closesocket(listenSocket);
		// Winsock End
		WSACleanup();
		return 1;
	}
	else
	{
		printf("Server Connected\n* Enter Message\n->");
	}
	
	SOCKETINFO *socketInfo;
	DWORD sendBytes;
	DWORD receiveBytes;
	DWORD flags;

	while (1)
	{		
		// 메시지 입력
		char messageBuffer[MAX_BUFFER];
		int i, bufferLen;
		for (i = 0; 1; i++)
		{
			messageBuffer[i] = getchar();
			if (messageBuffer[i] == '\n')
			{
				messageBuffer[i++] = '\0';
				break;
			}
		}
		bufferLen = i;
		
		socketInfo = (struct SOCKETINFO *)malloc(sizeof(struct SOCKETINFO));
		memset((void *)socketInfo, 0x00, sizeof(struct SOCKETINFO));		
		socketInfo->dataBuffer.len = bufferLen;
		socketInfo->dataBuffer.buf = messageBuffer;

		// 3-1. 데이터 쓰기
		int sendBytes = send(listenSocket, messageBuffer, bufferLen, 0);
		if (sendBytes > 0)
		{
			printf("TRACE - Send message : %s (%d bytes)\n", messageBuffer, sendBytes);
			// 3-2. 데이터 읽기
			int receiveBytes = recv(listenSocket, messageBuffer, MAX_BUFFER, 0);
			if (receiveBytes > 0)
			{
				printf("TRACE - Receive message : %s (%d bytes)\n* Enter Message\n->", messageBuffer, receiveBytes);
			}			
		}
		
	}		

	// 4. 소켓종료
	closesocket(listenSocket);

	// Winsock End
	WSACleanup();
	
	return 0;
}