//Ŭ̾Ʈ :ʱȭ-ϻ-connect-- 
#include<stdio.h> 
#include<stdlib.h> 
#include<string.h>
#include<winsock2.h> 
#include<conio.h>


#include <iostream>
#include <string>


#include <conio.h>
//Error: Getch Was Not Declared In This Scope
//https://www.dreamincode.net/forums/topic/341445-error-getch-was-not-declared-in-this-scope/

//htons function
//https://docs.microsoft.com/en-us/windows/desktop/api/winsock/nf-winsock-htons

//WinSock32  
//https://social.msdn.microsoft.com/Forums/vstudio/en-US/82ee2e1b-9957-4147-ac31-4e9ac82cbd59/winsock32?forum=vcgeneral

#include <locale.h>




// /workspace/test/src/client.c:76: error: _getch was not declared in this scope

#pragma comment(lib,"ws2_32.lib")
#define BUFSIZE 2048
 
void ErrorHandling(char *message);


using namespace std;



//[WinAPi]WinAPI ̿Ͽ cp949(ANSI) - utf8 ڵ ȯ   C/C++  
//http://blog.naver.com/PostView.nhn?blogId=nimi315&logNo=50093464158

//UTF-8  ANSI  ȯ (ѱ ¿ )
string utf8_to_ansi(string &utf8) 
{ 
    WCHAR unicode[1500]; 
    char ansi[1500]; 
 
    memset(unicode, 0, sizeof(unicode)); 
    memset(ansi, 0, sizeof(ansi)); 
 
    ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, unicode, sizeof(unicode)); 
    ::WideCharToMultiByte(CP_ACP, 0, unicode, -1, ansi, sizeof(ansi), NULL, NULL); 
 
    return string(ansi); 
}



//  Լ    
//fn_WSAGetLastError("recv Error\n", recv_len, __FUNCTION__, __LINE__);
void fn_WSAGetLastError(char* input_msg, int result, char* function_name, int line)
{
    LPVOID lpMsgBuf;
	DWORD dwWSAErrorCode;

	//
	dwWSAErrorCode = WSAGetLastError();
    FormatMessage(  FORMAT_MESSAGE_ALLOCATE_BUFFER|
                    FORMAT_MESSAGE_FROM_SYSTEM,
                    NULL, dwWSAErrorCode,
                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                    (LPTSTR)&lpMsgBuf, 0, NULL);
//    MessageBox(NULL, (LPCTSTR)lpMsgBuf, msg_input, MB_ICONERROR);
	printf("----------------------------------------\n");
	printf("function name     [%s()]\n",	function_name);
	printf("line number       [%d]\n",		line);
    printf("input_msg         [%s]\n",		input_msg);
    printf("result            [%d]\n",		result);
    printf("wsa_error_code    [%d]\n",		dwWSAErrorCode);
    printf("wsa_error_string  %s",			(LPCTSTR)lpMsgBuf);
	printf("----------------------------------------\n");
    LocalFree(lpMsgBuf);

	//  ' ǵ Ǿ . Ȳ ° ؼ ϼ. 
    system("PAUSE\n");
    exit(-1);   //or exit(0);
}





// (char*)
// /workspace/test/src/client.c:34: warning: deprecated conversion from string constant to char*

int main(int argc, char *argv[])
{
	
	//ѱ  
	setlocale(LC_ALL, "korean");
	
	//utf-8 ѱ ansi 
	string str = "Ŭ̾Ʈ";
	string r;
	r = utf8_to_ansi(str);
	cout << str << endl;
	cout << r << endl;
	printf("%s\n", r.c_str());
	
	
	//迭 
	char hex[] = "A003A0030101000E";
	char *ptr;
	long value;
	value = strtoul(hex, &ptr, 16);
 
 
 	// 
	SOCKET clientsock; 
	WSADATA wsa;
	struct sockaddr_in sockinfo; 
	char message[BUFSIZE]; 
 	int strlen;
	
	
	//ڰ 3 ƴϸ. 
	//client.exe argv[1] argv[2]
	if (argc != 3)
	{
		printf("Usage : %s <IP> <PORT> \n", argv[0]);
		exit(1);
	}
 
	//  ʱȭ
	if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
	{
		//ϸ WSASTartup Լ 0 ȯմϴ. ׷  Ʒ   ڵ  ϳ ȯմϴ.
		//https://docs.microsoft.com/ko-kr/windows/desktop/api/winsock/nf-winsock-wsastartup
		int r = WSAGetLastError();
		printf("WSAGetLastError() : %d\n", r);

		fn_WSAGetLastError((char*)"WSAStartup() Error\n", 0, (char*)__FUNCTION__, __LINE__);
		
		str = "Winsock DLL ";
		ErrorHandling((char*)utf8_to_ansi(str).c_str());
	}
 
	//TCP  
	clientsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (clientsock == INVALID_SOCKET)
	{
		//https://docs.microsoft.com/ko-kr/windows/desktop/api/winsock2/nf-winsock2-socket
		//If no error occurs, socket returns a descriptor referencing the new socket. 
		//Otherwise, a value of INVALID_SOCKET is returned, 
		//and a specific error code can be retrieved by calling WSAGetLastError.
		int r = WSAGetLastError();
		printf("WSAGetLastError() : %d\n", r);

		fn_WSAGetLastError((char*)"socket() Error\n", clientsock, (char*)__FUNCTION__, __LINE__);

		str = "Soecket  ";
		ErrorHandling((char*)utf8_to_ansi(str).c_str());
	}

	//struct sockaddr_in sockinfo ü ʱȭ
	memset(&sockinfo, 0, sizeof(sockinfo));
	//ּ йи 
	sockinfo.sin_family = AF_INET;
	//Ʈ ȣ 
	sockinfo.sin_port = htons(atoi(argv[2]));
	//IP ּ 
	sockinfo.sin_addr.s_addr = inet_addr(argv[1]);
 
	//  
	if (connect(clientsock, (SOCKADDR*)&sockinfo, sizeof(sockinfo)) == SOCKET_ERROR)
	{
		//https://docs.microsoft.com/ko-kr/windows/desktop/api/winsock2/nf-winsock2-connect
		//If no error occurs, connect returns zero. 
		//Otherwise, it returns SOCKET_ERROR, and a specific error code can be retrieved by calling WSAGetLastError.
		int r = WSAGetLastError();
		printf("WSAGetLastError() : %d\n", r);

		fn_WSAGetLastError((char*)"connect() Error\n", SOCKET_ERROR, (char*)__FUNCTION__, __LINE__);

		str = "connect ";
		ErrorHandling((char*)utf8_to_ansi(str).c_str());
	}
 
	//recv ޱ 
	//int recv( SOCKET s, __out_data_source(NETWORK) char *buf, int len, int flags );
	//https://docs.microsoft.com/en-us/windows/desktop/api/winsock/nf-winsock-recv
	//WSAGetLastError()
	//A set of flags that influences the behavior of this function. 
	//See remarks below. See the Remarks section for details on the possible value for this parameter.
	
	// / 迭  / 迭 ũ-1
	strlen = recv(clientsock, message, sizeof(message)-1, 0); 
	if (strlen == SOCKET_ERROR)
	{
		//   ϰ  ٸϴ.
		//ݵ MSDN  Լ  Ȯϰ. Ͻñ ٶϴ.
		
		//WSAGetLastError() ΰ ְ.
		//GetLastError() ΰ ְ.
		//int  ϰ 찡 ְ.
		//DWORD  ϰ 찡 ֽϴ.
		
		//FormatMessage()  ؼ.  ѱ    ֽϴ.
		
		// ߻  recv ŵ Ʈ  ȯϸ, 
		//buf Ű  Ű ۿ ŵ  Ͱ Ե˴ϴ. 
		//    ȯ  0Դϴ. 
		//׷  SOCKET_ERROR  ȯǰ WSAGetLastError ȭϿ Ư  ڵ带 ˻  ֽϴ.
		int r = WSAGetLastError();
		printf("WSAGetLastError() : %d\n", r);

		//fn_WSAGetLastError("recv Error\n", recv_len, __FUNCTION__, __LINE__);
		fn_WSAGetLastError((char*)"recv Error\n", strlen, (char*)__FUNCTION__, __LINE__);

		//int WSAGetLastError();
		//https://docs.microsoft.com/ko-kr/windows/desktop/api/winsock/nf-winsock-wsagetlasterror
		str = "recv ";
		ErrorHandling((char*)utf8_to_ansi(str).c_str());
	}


	// / 迭  / 迭 ũ-1
	strlen = recv(clientsock, hex, sizeof(hex)-1, 0);
	if(strlen == SOCKET_ERROR)
	{
		int r = WSAGetLastError();
		printf("WSAGetLastError() : %d\n", r);

		//fn_WSAGetLastError("recv Error\n", recv_len, __FUNCTION__, __LINE__);
		fn_WSAGetLastError((char*)"recv Error\n", strlen, (char*)__FUNCTION__, __LINE__);

		//int WSAGetLastError();
		//https://docs.microsoft.com/ko-kr/windows/desktop/api/winsock/nf-winsock-wsagetlasterror
		str = "recv ";
		ErrorHandling((char*)utf8_to_ansi(str).c_str());
	}
	

	//
	string str1 = " ʹ 16";
	string str2 = "Դϴ.";
	printf("%s 0x%08X %s\n", (char*)utf8_to_ansi(str1).c_str(), htons(strlen), (char*)utf8_to_ansi(str2).c_str());
	
	str1 = " ʹ ";
	str2 = "Դϴ.";
	printf("%s %d %s\n", (char*)utf8_to_ansi(str1).c_str(), strlen, (char*)utf8_to_ansi(str2).c_str());
 
 
	//
	printf(" Server say message: %s \n", message);
	printf(" Server say hex : %s \n", hex);
 
 	// 
	closesocket(clientsock); 
	
	// Cleanup
	WSACleanup();
	return 0;
}
 



//
void ErrorHandling(char *message) 
{
	WSACleanup();
	fputs(message, stderr);
	fputc('\n', stderr);
	_getch();
	exit(1);
}

