16. DLL.

Slides:



Advertisements
Similar presentations
TCP 서버/클라이언트 동작 원리 - (1) TCP 서버/클라이언트 예 웹 서버 웹 클라이언트 웹 클라이언트
Advertisements


2장. 프로그램의 기본 구성. 2장. 프로그램의 기본 구성 2-1"Hello, World!" 들여다 보기 /* Hello.c */ #include int main(void) { printf("Hello, World! \n"); return 0;
Network Lab. Byoung-Son, Choi
WSAAsync Select 김대열 Bit - Academy Sunmoon University, Korea.
10장. 소켓 입출력 모델(I) 블로킹과 넌블로킹 소켓의 특징을 이해한다. Select 소켓 입출력 모델을 이해하고 활용한다.
인공지능실험실 석사 2학기 이희재 TCP/IP Socket Programming… 제 11장 프로세스간 통신 인공지능실험실 석사 2학기 이희재
9장. C 언어의 핵심! 함수. 9장. C 언어의 핵심! 함수 9-1 함수의 정의와 선언 main 함수 다시 보기 : 함수의 기본 형태 { } 그림 9-1.
Network Lab. Young-Chul Hwang
Department of Computer Science and Engineering
Java로 배우는 디자인패턴 입문 Chapter 5. Singleton 단 하나의 인스턴스
제 9 장 구조체와 공용체.
컴퓨터 프로그래밍 기초 [Final] 기말고사
소켓 모델 주소 지정 in_addr_t inet_addr(const char *ip_address) 연결 지향 모델 (TCP)
Chapter 03. 소켓 주소 구조체 다루기.
조 병 규 Software Quality Lab. 한국교통대학교
윤성우의 열혈 C 프로그래밍 윤성우 저 열혈강의 C 프로그래밍 개정판 Chapter 12. 포인터의 이해.
제 6장. 생성자와 소멸자 학기 프로그래밍언어및실습 (C++).
쉽게 풀어쓴 C언어 Express 제17장 동적메모리와 연결리스트 C Express Slide 1 (of 13)
제 14장 Multicast & Broadcast
Department of Computer Engineering
한남대학교 컴퓨터공학과 컴퓨터 네트워크 실험실
Department of Computer Engineering
인공지능실험실 석사 2학기 이희재 TCP/IP Socket Programming… 제 7장 소켓 연결의 우아한 종료 인공지능실험실 석사 2학기 이희재
Linux서버를 이용한 채팅프로그램 지도 교수님 : 이형원 교수님 이 름 : 이 은 영 학 번 :
07. 디바이스 드라이버의 초기화와 종료 김진홍
CHAPTER 02 OpenCV 개요 PART 01 영상 처리 개요 및 OpenCV 소개.
8장. 원격지 시스템 관리하기.
네트워크 프로그래밍 Yang-Sae Moon Department of Computer Science
11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.
Chapter 06. UDP 서버/클라이언트.
인공지능실험실 박사 1학기 장성만 TCP/IP Socket Programming… 9장 소켓의 다양한 옵션 인공지능실험실 박사 1학기 장성만
TCP/IP 응용 프로그램에 적용 가능한 다양한 소켓 옵션을 이해하고 활용한다.
메시지 큐[5] – test1.c 메시지 제어: msgctl(2) #include <sys/msg.h>
프로젝트 발표 순서 12/7(수), 팀 별 15분 발표순서 PPT (팀 별 이름, 구현 내용, 결과-그래프 포함) 각 기법당
Department of Computer Science and Engineering
13장 고급 입출력 함수 박사 4학기 최 성자.
TCP/IP Socket Programming…
Chapter 03. 소켓 주소 구조체 다루기.
Socket Address Structure and Byte Ordering Functions
Socket Address Structure and Byte Ordering Functions
UDP Test 프로그램 분석.
Chapter 5 UDP Socket 소켓 프로그래밍.
WOL(Wake-On Lan) 컴퓨터공학과 4학년 박기웅.
3장 상수 변수 기본 자료형 키워드와 식별자 상수와 변수 기본 자료형 형변환 자료형의 재정의.
TCP/IP 응용 프로그램에 적용 가능한 다양한 소켓 옵션을 이해하고 활용한다.
GUI 소켓 애플리케이션 Chapter 08. * 학습목표 윈도우 GUI 애플리케이션의 구조와 동작 원리를 이해
HTTP 프로토콜의 요청과 응답 동작을 이해한다. 서블릿 및 JSP 를 알아보고 역할을 이해한다.
24장. 파일 입출력.
Lesson 2. 기본 데이터형.
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
WSAAsync Select 김대열 Bit - Academy Sunmoon University, Korea.
컴퓨터 프로그래밍 기초 - 10th : 포인터 및 구조체 -
Network Programming - 최종보고서 -
Department of Computer Engineering
IOCP 2005/11/10.
컴퓨터 프로그래밍 기초 - 8th : 함수와 변수 / 배열 -
자바로 만든 채팅 프로그램 임경진 조주경 지도교수님 : 이광세 교수님.
Chapter 04. TCP 서버/클라이언트.
Chapter 02. 윈도우 소켓 시작하기.
구조체(struct)와 공용체(union)
인공지능실험실 박사 1학기 장성만 TCP/IP Socket Programming… 제 8장 도메인 이름과 인터네 주소 인공지능실험실 박사 1학기 장성만
Numerical Analysis Programming using NRs
바이트 순서 변환 함수 주소 변환 함수 바이트 조작 함수 원격지 호스트 정보를 얻는 함수
엔코더 프로그램 설명 // 쓰레드를 사용하기 때문에 변수와 핸들을 전역변수로 지정 HANDLE hDevice;
Network Lab. Young-Chul Hwang
Completion Port기반의 채팅프로그램
Reversing 발표자 : 박현우.
CODE INJECTION 시스템B 김한슬.
6 객체.
Presentation transcript:

16. DLL

1. DLL (Dynamic Link Library) Microsoft Windows의 가장 중요한 구조적 요소 중 하나이다. 라이브러리의 기초 DLL은 직접 실행될 수 없다. 메시지를 받지 않는다. 프로그램에서 호출되는 함수들을 가진 별도의 파일이다. 프로그램이 라이브러리 내의 함수들 중 하나를 호출할 때만 동작한다. 확장자가 DLL이면 자동으로 로드 된다. DLL의 목적 다수의 서로 다른 프로그램들에 의해 사용될 수 있는 함수와 자원을 제공 DllMain DLL이 실행 파일에 의해 요청되거나 해제될 때 호출된다. DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) hInstance : 라이브러리의 인스턴스 핸들 dwReason : Windows가 DllMain을 호출하는 이유 DLL_PROCESS_ATTACH 동적 연결 라이브러리가 프로세스의 주소 공간으로 매핑되어 있음을 나타낸다. 프로세스가 수행되는 동안 오직 한번의 호출된다.

1. DLL (Dynamic Link Library) DLL_PROCESS_DETACH 해당 프로세스에 DLL이 더 이상 필요로 하지 않는다는것을 의미한다. 라이브러리가 자신을 정리한다. DLL_THREAD_ATTACH 추가된 프로세스가 새로운 스레드를 만든다. DLL_THREAD_DETACH 스레드가 종료될 때 Window는 호출한다. 우선 함수를 제공하는 DLL에서는 자신이 제공하는 함수에 대한 정보를 밖으로 공개해 놓아야 한다. Export DLL을 사용하는 클라이언트에서는 어떤 DLL에 있는 어떤 함수를 사용하겠다고 선언해야 한다. Import __declspec ( extended-decl-modifier-seq ) 함수에 대한 정보를 제공하는 선언문이며 엑스포트 또는 임포트하는 함수 앞에 수식어로 이문구가 있어야 한다. extern "C" __declspec(dllexport) int InitHook( HINSTANCE hDll, HWND hWndHost ) extern "C" typedef __declspec(dllimport) int (*PFNInitHook)( HINSTANCE hDll, HWND hWndHost ); extern "C" typedef __declspec(dllimport) void (*PFNGetDeadWndTxt)( char *pszBuf, int nMaxBuf ); extern "C" typedef __declspec(dllimport) void (*PFNReleaseHook)();

1. DLL (Dynamic Link Library) extern “C” mangled name을 만들지 않도록 지정함으로써 C형식으로 함수의 정보를 공개하도록 한다. 명시적 연결 m_hInstDll = ::LoadLibrary( "l3t_hook.dll" ); if( !m_hInstDll ) { MessageBox( "l3t_hook.dll 을 찾을 수 없습니다.", "오류" ); return FALSE; } m_pfnInitHook = (PFNInitHook)::GetProcAddress( m_hInstDll, "InitHook" ); m_pfnReleaseHook = (PFNReleaseHook)::GetProcAddress( m_hInstDll, "ReleaseHook" ); m_pfnGetDeadWndTxt = (PFNGetDeadWndTxt)::GetProcAddress( m_hInstDll, "GetDeadWndTxt" ); if( (!m_pfnInitHook) || (!m_pfnReleaseHook) ) { MessageBox( "잘못된 dll입니다.", "오류" ); ::FreeLibrary( m_hInstDll ); m_hInstDll = 0;

17. 소켓의 기초

1. 서버 소켓 소켓이 작업하는 방식 서버 소켓 1. 연결의 기다리는 소켓 : 서버 소켓 2. 연결을 시도하는 소켓 : 클라이언트 소켓 서버 소켓 연결을 시도하는 클라이언트 소켓과의 연결을 구축한다. 서버 소켓은 데이터의 흐름에 대해서는 신경 쓰지 않는다. 오직 연결만 처리한다. 데이터의 흐름은 같은 프로그램 내의 다른 소켓이 담당하게 된다. 서버 클라이언트 (원격 소켓) (로컬 소켓) 1. 연결 시도 2. 소켓 생성 3. 연결 및 데이터 송수신

1. 서버 소켓 연결을 시도하는 소켓은 무조건 큐에 들어간다. 큐에 들어가서 자신이 처리될 순서를 기다린다. 1. 서버 소켓이 존재하는 상태에서 원격 소켓이 연결을 시도 2. 서버 소켓은 패킷 송수신을 담당할 로컬 소켓을 생성 3. 로컬 소켓과 연결을 시도한 원격 소켓을 연결 4. 서버 로컬 소켓과 원격 소켓 간의 데이터 송수신 연결을 시도하는 소켓은 무조건 큐에 들어간다. 큐에 들어가서 자신이 처리될 순서를 기다린다. 서버 소켓은 큐에 들어 있는 원격 소켓을 하나씩 처리한다.

1. 서버 소켓 서버 소켓 흐름도 소켓 생성 : socket() 1회 실행 결합 : bind() 듣기 : listen () 항상, 참 대기 : Accept() 로컬 소켓 생성 연결구축, 로컬 소켓과 원격 소켓 1회 실행 무한 반복

#include <winsock2.h> #include <windows.h> #include "resource.h" BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData); DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc) ; WSACleanup(); return TRUE; } BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) static HWND hEdit1,hEdit2; static HWND hButton1,hButton2; static SOCKET hServerSock; static SOCKET hClientSock; switch (message) case WM_INITDIALOG : hEdit1 = GetDlgItem(hDlg,IDC_EDIT1); hEdit2 = GetDlgItem(hDlg,IDC_EDIT2); hButton1 = GetDlgItem(hDlg,IDC_BUTTON1); hButton2 = GetDlgItem(hDlg,IDC_BUTTON2); EnableWindow(hButton1,FALSE); EnableWindow(hButton2,FALSE); hServerSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); sockaddr_in ServerAddr; ZeroMemory(&ServerAddr,sizeof(sockaddr_in)); ServerAddr.sin_addr.s_addr = ADDR_ANY; ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(50000);

bind(hServerSock,(sockaddr *)&ServerAddr,sizeof(sockaddr_in)); listen(hServerSock,SOMAXCONN); SetWindowText(hEdit1,"클라이언트 접속을 기다리고 있습니다."); } return TRUE ; case WM_COMMAND : switch (LOWORD (wParam)) { case IDC_ACCEPT: sockaddr_in ClientAddr; int nAddrLen = sizeof(ClientAddr); hClientSock = accept(hServerSock,(sockaddr *)&ClientAddr,&nAddrLen); if (hClientSock == INVALID_SOCKET) int ErrorCode = WSAGetLastError(); char errMsg[1024]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,NULL,ErrorCode,0,errMsg,1204,NULL); MessageBox(NULL,errMsg,"",MB_OK); char temp[256]; wsprintf(temp,"%s 클라이언트 접속 요청",inet_ntoa(ClientAddr.sin_addr)); SetWindowText(hEdit1,temp); EnableWindow(hButton1,TRUE); EnableWindow(hButton2,TRUE); return TRUE; case IDC_BUTTON1: recv(hClientSock,temp,256,NULL); SetWindowText(hEdit2,temp);

case IDC_BUTTON2: { char temp[256]; GetWindowText(hEdit2,temp,256); send(hClientSock,temp,256,NULL); return TRUE; } case IDOK : case IDCANCEL : closesocket(hServerSock); closesocket(hClientSock); EndDialog (hDlg, 0) ; return TRUE ; break ; return FALSE ;

1. 서버 소켓 accept 함수 클라이언트 소켓이 연결을 시도할 때까지 블로킹상태에 빠지기 때문에 프로그램이 죽은 것처럼 보인다. 첫 번째 인자 : 대기 모드에 들어가 있는 소켓의 핸들. 반드시 listen 함수 호출에서 성공한 핸들이어야 한다. 두 번째 인자 : 연결을 시도한 클라이언트 소켓의 번호를 받을 sockaddr_in 구조체의 주소 세 번째 인자 : 두 번째 인자로 들어가는 구조체의 크기 원격지에서 연결을 시도한 소켓과 연결을 담당한다. 두 번째 인자를 통하여 넘어온 IP를 확인하여 연결을 허락할지 끊어야 할지를 결정한다. 연결을 끊을 때는 closesocket함수를 이용하낟. 리턴 값 : 원격지 소켓과의 데이터 송수신을 처리할 소켓의 핸들을 반환한다. (accept함수 내부에서 생성) 실패하면 INVALID_SOCKET 이 리턴된다. accept함수가 성공하면 프로그램에는 소켓이 두 개가 존재하게 된다.

2. 클라이언트(원격) 소켓 원격 소켓 원격 소켓의 역할은 서버 소켓에 연결을 시도하는 것이다. 원격 소켓이 서버에 연결하기 위해서는 반드시, 서버의 주소와 포트 번호를 알고 있어야 한다. 클라이언트 프로그램이 종료되면, 원격 소켓은 자동으로 종료된다. 소켓은 종료할 때, 자신과 연결된 상대 소켓에게 종료되었다고 알려 준다.

2. 클라이언트(원격) 소켓 클라이언트(원격) 소켓 흐름도 소켓 생성 : socket() 1회 실행 서버에 연결 : connect () 연결 ? 데이터 송수신 send(),receive() 1회 실행 무한 반복 실패 작업 완료? 성공 종료 : closesocket() 예

#include <winsock2.h> #include <windows.h> #include "resource.h" BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData); DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc) ; WSACleanup(); return TRUE; } BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) static HWND hEdit1,hEdit2; static HWND hButton1,hButton2; static SOCKET hClientSock; switch (message) case WM_INITDIALOG : hEdit1 = GetDlgItem(hDlg,IDC_EDIT1); hEdit2 = GetDlgItem(hDlg,IDC_EDIT2); hButton1 = GetDlgItem(hDlg,IDC_BUTTON1); hButton2 = GetDlgItem(hDlg,IDC_BUTTON2); EnableWindow(hButton1,FALSE); EnableWindow(hButton2,FALSE); hClientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); return TRUE ;

case WM_COMMAND : switch (LOWORD (wParam)) { case IDC_CONNECT: sockaddr_in ServerAddr; ZeroMemory(&ServerAddr,sizeof(sockaddr_in)); ServerAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(50000); connect(hClientSock,(sockaddr *)&ServerAddr,sizeof(ServerAddr)); SetWindowText(hEdit1,"서버에 접속되었습니다."); EnableWindow(hButton1,TRUE); EnableWindow(hButton2,TRUE); return TRUE; } case IDC_BUTTON1: char temp[256]; recv(hClientSock,temp,256,NULL); SetWindowText(hEdit2,temp); case IDC_BUTTON2: GetWindowText(hEdit2,temp,256); send(hClientSock,temp,256,NULL); case IDOK : case IDCANCEL : closesocket(hClientSock); EndDialog (hDlg, 0) ; return TRUE ; break ; return FALSE ;

3. TCP UDP 연결이 존재하지 않는다. 최선형 (best effort) 프로토콜로 최선을 다해서 데이터가 도착하도록 노력은 하지만, 도착하지 않아도 책임은 지지 않는다. 도착하지 않았을 때의 책임은 각각의 프로그램에서 담당한다. 연결이 존재하지 않기 때문에 각각의 패킷은 서로 연관성이 없어야 한다. 전송 패킷은 반드시 한 번에 전송되어야 한다. TCP의 경우는 여러 번에 걸쳐 전송될 수도 있다. TCP TCP프로토콜은 가상으로 연결된 상태이다. 한 번에 전송한 패킷이 한번에 전송될 수도 있고 여러 번에 걸쳐서 전송될 수도 있다.

3. TCP 여러 번에 걸쳐서 전송된 패킷이 한번에 전송될 수도 있다. 연결이 된 이후부터 연결을 닫을 때까지 전송한 데이터가 모두 하나의 데이터이다. TCP에서는 어디서부터 어디까지가 의미 있는 하나의 패킷인지 확인하는 작업이 필수적이다. 전송 측과 수신 측 모두 두 개의 버퍼를 사용한다. 애플리케이션 버퍼, 전송 또는 수신을 위한 소켓 라이브러리 버퍼 send 함수를 호출했다고 해서 패킷이 실제로 상대 소켓으로 전달되었다고 가정해서는 안 된다. send함수는 소켓 라이브러리의 버퍼로 데이터를 옮겨놓는 순간 반환된다. 만약에 소켓 라이브러리 버퍼가 꽉 차면 블로킹 상태가 된다. 상대 소켓으로 데이터를 전송하고 나서 버퍼에 여유가 생겨서 send함수가 모든 데이터를 이동하면, 그때 블로킹이 풀린다. TCP 프로토콜에서 연결이 구축되어 있는 동안 전송되는 패킷은 모두 연속되어 있다. 패킷을 처리할 때는, 각각의 패킷 길이만큼 잘라서 처리해야 한다.

4. 패킷 패킷은 크게 두 부분으로 나뉜다. ( 헤더와 데이터 ) 헤더에는 반드시 전체 패킷의 크기가 들어가야 한다. 한 패킷을 잘라 오기 위하여 패킷 헤더는 일반적으로 어떠한 패킷이던지 동일한 길이로 구성한다. 패킷 전체 길이 (4byte) 식별자 헤더 로그인 24 LOGIN 회원ID (8byte) PassWord 파일요청 80 FILE_REQUEST 파일의 HashKey (64byte) 파일 전송 파일길이+8 FILE_TRANSFER 파일내용 가변길이

18. 소켓 초기화

1. WSAStartup함수 윈도우 소켓을 초기화한다. Ws2_32.dll함수를 응용 프로그램의 영역으로 로드한다. WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData); WSADATA구조체 변수는 WSAStartup함수가 반환하는 윈도우 소켓의 세부 정보를 가져 온다. 첫 번째 인자에는 소켓 라이브러리의 버전을 저장한다. 하위 바이트에는 메이저 버전 : 2 상위 바이트에는 마이너 버전 : 2 MAKEWORD(하위, 상위) MAKEWORD(3,5) : 이 코드는 윈도우 버전 3.5를 의미한다.

2. WSACleanup함수 윈도우 소켓을 종료하는 함수이다. Ws2_32.dll을 사용하지 못하게 한다.

3. 메모리 바이트 순서 htons 함수 ntohs 함수 인텔 계열의 CPU는 리틀 엔디안이라는 방식으로 데이터를 메모리에 저장한다. 16진수 “2F78”은 782F로 메모리에 저장된다. 모토로라의 CPU는 빅 엔디안이라는 방식으로 데이터를 메모리에 저장한다. 16진수 “2F78”은 2F78 네트워크 바이트 순서는 빅 엔디언을 이용합니다. htons 함수 htons 함수는 “host to network short”의 약자이다. 호스트 바이트 순서로 되어있는 unsigned short를 네트워크 바이트 순서로 변환한다. 이 함수는 소켓 프로그래밍에서 포트 번호를 변환하기 위해서 사용한다. ntohs 함수 ntohs 함수는 “network to host short”의 약자이다. 네트워크 바이트 순서로 되어 있는 unsigned short자료형을 호스트 바이트 순서로 변환한다.

3. 메모리 바이트 순서 htonl함수 ntohl함수 inet_ntoa함수 inet_addr함수 htonl함수는 “host to network long”의 약자이다. 이 함수는 호스트 바이트 순서로 된 unsigned long자료형을 네트워크 바이트 순서로 변환한다. 이 함수는 소켓 프로그래밍에서 IP주소를 변환하기 위해 사용한다. ntohl함수 ntohl함수는 “network to host long”의 약자이다. 네트워크 바이트 순서로 된 unsigned long자료형을 호스트 바이트 순서로 변환한다. inet_ntoa함수 4바이트로 된 IP주소를 도트 표기법에 기반한 문자열로 변환한다. 클라이언트의 주소를 문자열로 변환해서 보여줄 때 사용 inet_addr함수 inet_addr함수는 internet address의 약자이다. 도트 표기법으로 되어 있는 주소 문자열을 4바이트 IP주소로 변환

19. 파일 전송

1. TransmitFile함수 hSocket : 파일을 보낼 소켓의 핸들 hFile : 전송할 파일의 핸들 BOOL TransmitFile( SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesToWrite, DWORD nNumberOfBytesPerSend, LPOVERLAPPED lpOverlapped, LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, DWORD dwFlags ); hSocket : 파일을 보낼 소켓의 핸들 hFile : 전송할 파일의 핸들 nNumberOfBytesToWrite : 전송할 양으로 파일 전체를 전송할 때는 0을 사용한다. nNumberOfBytesPerSend : 한 번에 전송할 패킷의 크기. 패킷의 크기를 시스템에 맡길 경우, 0을 사용한다. lpOverlapped : 중첩 입출력 구조체로 비동기 작업을 수행할 수 있도록 한다. lpTransmitBuffers : 파일을 전송하기 전에 전송할 헤더와 전송 후에 전송할 테일을 가리키는 구조체 포인터이다.

#include <winsock2.h> #include <windows.h> #include "resource.h" #include <commctrl.h> #include <Mswsock.h> BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData); DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc) ; WSACleanup(); return TRUE; } void DispErrorMessage() DWORD ErrorCode = GetLastError(); char errMsg[1024]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,NULL,ErrorCode,0,errMsg,1204,NULL); MessageBox(NULL,errMsg,"",MB_OK); BOOL GetFileName(char temp[]) strcpy(temp,"123.txt"); OPENFILENAME ofn; ZeroMemory(&ofn,sizeof(ofn)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = NULL; ofn.lpstrFilter = "모든 파일(*.*)\0*.*\0텍스트 파일(*.txt)\0*.txt\0\0\0"; ofn.lpstrFile = temp; ofn.nFilterIndex = 2; ofn.nMaxFile = 256; ofn.Flags = OFN_EXPLORER | OFN_ALLOWMULTISELECT | OFN_ENABLESIZING ; return GetOpenFileName(&ofn);

typedef struct Tansmitstruct { char pFileName[256]; int nFileSize; }TRANSMITSTRUCT; BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) static HWND hEdit1; static HWND hButton1; static SOCKET hServerSock; static SOCKET hClientSock; switch (message) case WM_INITDIALOG : hEdit1 = GetDlgItem(hDlg,IDC_EDIT1); hButton1 = GetDlgItem(hDlg,IDC_BUTTON1); EnableWindow(hButton1,FALSE); hServerSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); sockaddr_in ServerAddr; ZeroMemory(&ServerAddr,sizeof(sockaddr_in)); ServerAddr.sin_addr.s_addr = ADDR_ANY; ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(50000); bind(hServerSock,(sockaddr *)&ServerAddr,sizeof(sockaddr_in)); listen(hServerSock,SOMAXCONN); SetWindowText(hEdit1,"클라이언트 접속을 기다리고 있습니다."); } return TRUE ;

case WM_COMMAND : switch (LOWORD (wParam)) { case IDC_ACCEPT: sockaddr_in ClientAddr; int nAddrLen = sizeof(ClientAddr); hClientSock = accept(hServerSock,(sockaddr *)&ClientAddr,&nAddrLen); if (hClientSock == INVALID_SOCKET) int ErrorCode = WSAGetLastError(); char errMsg[1024]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,NULL,ErrorCode,0,errMsg,1204,NULL); MessageBox(NULL,errMsg,"",MB_OK); } char temp[256]; wsprintf(temp,"%s 클라이언트 접속 요청",inet_ntoa(ClientAddr.sin_addr)); SetWindowText(hEdit1,temp); EnableWindow(hButton1,TRUE); return TRUE; case IDC_BUTTON1: char TransFileName[256]; if (GetFileName(TransFileName) == FALSE) wsprintf(temp,"%s 파일을 전송합니다.",TransFileName); HANDLE hFile = CreateFile(TransFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL); if (hFile == INVALID_HANDLE_VALUE) DispErrorMessage();

BY_HANDLE_FILE_INFORMATION fileinfo; GetFileInformationByHandle(hFile,&fileinfo); char FileName[256]; char FileExt[256]; _splitpath(TransFileName,NULL,NULL,FileName,FileExt); strcat(FileName,FileExt); TRANSMITSTRUCT transmitstruct; transmitstruct.nFileSize = fileinfo.nFileSizeLow; strcpy(transmitstruct.pFileName,FileName); TRANSMIT_FILE_BUFFERS TransBuf; ZeroMemory(&TransBuf,sizeof(TRANSMIT_FILE_BUFFERS)); char pTailMsg[32] = "End Of File"; TransBuf.Head = &transmitstruct; TransBuf.HeadLength = sizeof(transmitstruct); TransBuf.Tail = pTailMsg; TransBuf.TailLength = sizeof(pTailMsg); BOOL bTrans = TransmitFile(hClientSock,hFile,0,0,NULL,&TransBuf,0); if (bTrans == FALSE) { DispErrorMessage(); } CloseHandle(hFile); SetWindowText(hEdit1,"파일 전송을 완료했습니다."); return TRUE; case IDOK : case IDCANCEL : closesocket(hServerSock); closesocket(hClientSock); EndDialog (hDlg, 0) ; return TRUE ; break ; return FALSE ;

#include <winsock2.h> #include <windows.h> #include <commctrl.h> #include "resource.h" BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData); DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc) ; WSACleanup(); return TRUE; } void DispErrorMessage() DWORD ErrorCode = GetLastError(); char errMsg[1024]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,NULL,ErrorCode,0,errMsg,1204,NULL); MessageBox(NULL,errMsg,"",MB_OK); typedef struct Tansmitstruct char pFileName[256]; int nFileSize; }TRANSMITSTRUCT;

BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hEdit1; static HWND hButton1,hProgress; static SOCKET hClientSock; switch (message) case WM_INITDIALOG : hEdit1 = GetDlgItem(hDlg,IDC_EDIT1); hButton1 = GetDlgItem(hDlg,IDC_BUTTON1); hProgress = GetDlgItem(hDlg,IDC_PROGRESS1); EnableWindow(hButton1,FALSE); hClientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); } return TRUE ; case WM_COMMAND : switch (LOWORD (wParam)) case IDC_CONNECT: sockaddr_in ServerAddr; ZeroMemory(&ServerAddr,sizeof(sockaddr_in)); ServerAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(50000); connect(hClientSock,(sockaddr *)&ServerAddr,sizeof(ServerAddr)); SetWindowText(hEdit1,"서버에 접속되었습니다."); EnableWindow(hButton1,TRUE); return TRUE;

case IDC_BUTTON1: { SetWindowText(hEdit1,"서버에서 파일을 수신 중입니다."); SendMessage(hProgress,PBM_SETRANGE32,0,0); SendMessage(hProgress,PBM_SETPOS,0,0); TRANSMITSTRUCT transstruct; int nTotalSize = sizeof(TRANSMITSTRUCT); int nTotalRecv = 0; do{ int nReceived = recv(hClientSock,(char *)(&transstruct+nTotalRecv),nTotalSize-nTotalRecv,0); nTotalRecv += nReceived; }while(nTotalSize != nTotalRecv); SendMessage(hProgress,PBM_SETRANGE32,0,transstruct.nFileSize); char temp[256]; wsprintf(temp,"%s(크기 : %d k)파일 수신 중 입니다.",transstruct.pFileName,transstruct.nFileSize); SetWindowText(hEdit1,temp); HANDLE hFile = CreateFile(transstruct.pFileName,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL); if (hFile == INVALID_HANDLE_VALUE) DispErrorMessage(); return TRUE; } BYTE pFileBuf[1024]; nTotalSize = transstruct.nFileSize; nTotalRecv = 0;

do{ DWORD dwByteRead; if ( (nTotalSize-nTotalRecv) > sizeof(pFileBuf)) dwByteRead = sizeof(pFileBuf); else dwByteRead = nTotalSize-nTotalRecv; int nReceived = recv(hClientSock,(char *)&pFileBuf,dwByteRead,0); if (nReceived == SOCKET_ERROR) { DispErrorMessage(); CloseHandle(hFile); return TRUE; } nTotalRecv += nReceived; DWORD dwByteWritten = 0; WriteFile(hFile,pFileBuf,dwByteRead,&dwByteWritten,NULL); SendMessage(hProgress,PBM_SETPOS,nTotalRecv,0); }while(nTotalSize != nTotalRecv); nTotalSize = 32; nTotalRecv = 0; int nReceived = recv(hClientSock,(char *)&pFileBuf+nTotalRecv,nTotalSize-nTotalRecv,0); SetWindowText(hEdit1,"파일 수신을 완료했습니다."); case IDOK : case IDCANCEL : closesocket(hClientSock); EndDialog (hDlg, 0) ; return TRUE ; break ; return FALSE ;

20. 1 대 1 채팅

#include <winsock2.h> #include <windows.h> #include <commctrl.h> #include "resource.h" #define WM_SOCKTEVENT WM_USER+100 void DispErrorMessage() { DWORD ErrorCode = GetLastError(); char errMsg[1024]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,NULL,ErrorCode,0,errMsg,1204,NULL); MessageBox(NULL,errMsg,"",MB_OK); } BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); HINSTANCE hInst; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData); hInst = hInstance; HMODULE hMod = LoadLibrary("RICHED32.DLL"); InitCommonControls(); DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc) ; FreeLibrary(hMod); WSACleanup(); return TRUE;

BOOL CALLBACK DlgProc2 (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hIPCtrl; static HWND hRadio1,hRadio2; switch (message) case WM_INITDIALOG : hIPCtrl = GetDlgItem(hDlg,IDC_IPADDRESS1); hRadio1 = GetDlgItem(hDlg,IDC_RADIO1); hRadio2 = GetDlgItem(hDlg,IDC_RADIO2); SendMessage(hRadio1,BM_SETCHECK,TRUE,NULL); EnableWindow(hIPCtrl,FALSE); } return TRUE ; case WM_COMMAND : switch (LOWORD (wParam)) case IDC_RADIO1: case IDC_RADIO2: EnableWindow(hIPCtrl,TRUE); case IDOK : case IDCANCEL : if (SendMessage(hRadio1,BM_GETCHECK,NULL,NULL)) EndDialog (hDlg, 0) ; else DWORD nAddress; int nIP = (int)SendMessage(hIPCtrl,IPM_GETADDRESS,0,(LPARAM)&nAddress); if (nIP != 4) MessageBox(hDlg,"IP주소를 모두 입력하세요",NULL,MB_OK); EndDialog (hDlg, nAddress) ; break ; return FALSE ;

BOOL CALLBACK DlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hRichEdit1,hEdit1; static HWND hButton1; static SOCKET hClientSock; static SOCKET hServerSock; switch (message) case WM_INITDIALOG : hEdit1 = GetDlgItem(hDlg,IDC_EDIT1); hRichEdit1 = GetDlgItem(hDlg,IDC_RICHEDIT1); hButton1 = GetDlgItem(hDlg,IDC_BUTTON1); EnableWindow(hButton1,FALSE); UpdateWindow(hDlg); DWORD dwIP = DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG2), NULL, DlgProc2) ; if (dwIP == 0) hServerSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); sockaddr_in ServerAddr; ZeroMemory(&ServerAddr,sizeof(sockaddr_in)); ServerAddr.sin_addr.s_addr = ADDR_ANY; ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(50000); bind(hServerSock,(sockaddr *)&ServerAddr,sizeof(sockaddr_in)); listen(hServerSock,SOMAXCONN); WSAAsyncSelect(hServerSock,hDlg,WM_SOCKTEVENT,FD_ACCEPT); SetWindowText(hDlg,"서버"); }

else { hClientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); sockaddr_in ServerAddr; ZeroMemory(&ServerAddr,sizeof(sockaddr_in)); ServerAddr.sin_addr.s_addr = htonl(dwIP); ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(50000); connect(hClientSock,(sockaddr *)&ServerAddr,sizeof(ServerAddr)); WSAAsyncSelect(hClientSock,hDlg,WM_SOCKTEVENT,FD_READ|FD_CLOSE); SetWindowText(hDlg,"클라언트"); } EnableWindow(hButton1,TRUE); return TRUE ; case WM_SOCKTEVENT: int nEvent = LOWORD(lParam); int nError = HIWORD(lParam); switch(nEvent) case FD_ACCEPT: sockaddr_in ClientAddr; int nAddrLen = sizeof(ClientAddr); hClientSock = accept(hServerSock,(sockaddr *)&ClientAddr,&nAddrLen); closesocket(hServerSock); hServerSock = INVALID_SOCKET; break; case FD_READ: char temp[256]; int nReceived = recv(hClientSock,temp,256,NULL); SetWindowText(hRichEdit1,temp);

case FD_CLOSE: { closesocket(hClientSock); hClientSock = INVALID_SOCKET; MessageBox(hDlg,"상대방에서 연결을 종료했습니다.",NULL,MB_OK); } break; return TRUE; case WM_COMMAND : switch (LOWORD (wParam)) case IDC_BUTTON1: char temp[256]; GetWindowText(hEdit1,temp,256); send(hClientSock,temp,256,NULL); return TRUE ; case IDOK : case IDCANCEL : EndDialog (hDlg, 0) ; break ; return FALSE ;