반응형
//file server
#define WIN32_LEAN_AND_MEAN // windows.h 에서 자주 사용하지 않은 것은 컴파일에서 제외 한다. // winsock2.h외의 충돌을 막아 준다. #include<stdio.h> #include<windows.h> #include<winsock2.h> #include<vector>// STL의 vector using namespace std; #pragma comment(lib, "ws2_32.lib") char filename[260] = "C:\\a.zip"; //전송할 파일 struct FILE_INFO { char FileName[260]; //전송할 파일 이름 int size; //파일 크기 }; //전속한 클라이언트에게 파일을 보낸다. DWORD WINAPI FileServer(void * p) { SOCKET s = (SOCKET)p; //전송할 파일 오픈 HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if(hFile == INVALID_HANDLE_VALUE) { printf("Can't Open File\n"); closesocket(s); return 0; } //크기를 구하고 파일의 정보를 전송한다. DWORD size1; DWORD size2 = GetFileSize(hFile, &size1); FILE_INFO fi; strcpy(fi.FileName, filename); fi.size = size2; send(s,(char *)&fi, sizeof(fi), 0); //----------------------------------------------------- //파일 전송 int total = size2; //전송할 전체 크기 int current = 0 ; //전송한 크기 int nRead = 0; char buf[4096]; //4K버퍼 while(total > current) { DWORD len; nRead = ReadFile(hFile, buf, 4096, &len, 0); if(len <= 0)break; int nSend = send( s, buf, len, 0 ); if(nSend <= 0) break; current += nSend; } if(total != current ) printf("전송 에러\n"); else printf("전송완료]\n"); closesocket(s); return 0; } void main() { WSADATA wsadata; //if(WSAStartup(0x0202, &wsadata) != 0) //0x0202는 뒤에서부터 읽어서 2.2버젼을 쓰라는 이야기다. if(WSAStartup(MAKEWORD(2,2), &wsadata) != 0) //많이 사용... 앞에서 부터 읽는다. { printf("Can't Initialize Socket !\n"); return ; } //------------------------------------------ //1. socket생성 : TCP: SOCK_STREAM : UDP :SOCK_DGRAM SOCKET s = socket(AF_INET, SOCK_STREAM, 0); //2. 생성된 소켓에 주소를 지정. SOCKADDR_IN addr = { 0 }; addr.sin_family = AF_INET; // 주소 종류 (AF_INET : IP 주소라는 의미.. addr.sin_port = htons(5000); //Port # addr.sin_addr.s_addr = INADDR_ANY;//inet_addr("61.81.99.54"); if(bind(s,(SOCKADDR*)&addr, sizeof(addr)) == -1) //서버의 닫혀 있는 상태를 대기 상태로 바꿔준다. 이순간 소켓은 내부적으로 접속요청 큐와 접속 완료 큐가 만들어진다. { printf("Can't bind \n"); return; } //3. 소켓을 대기 상태로 전환한다. if(listen(s, 10) == -1) { printf("Can't Listen\n"); closesocket(s); // 소켓 닫기 return; } printf("클리이언트를 대기합니다. \n"); //4. 이제 Client 에서 부터 전달된 요청을 허용한다. while(1) { SOCKADDR_IN c_addr; int size = sizeof(c_addr); SOCKET c_s = accept(s, (SOCKADDR*)&c_addr, &size); //억셉트를 눌렀는데 대기 큐에 아무도 없으면 대기한다. //억셉트를 누르는 순간 새로운 소켓을 만들어서 //상태를 연걸상태로 //IP는 자신의 IP로 포트는 놀고있는 임의의 포트로 설정해준다.->4000번 포트로 접속해서 다른포트로 통신 //상대 IP와 상대 포트를 지정... 상대의 포트도 접속후에는 통신하는 포트로 지정한다. //->접속하는 소켓은 대기만하고 접속하면 새로운 소켓이 통신을 한다. printf("클라이언트가 접속했습니다. IP : %s\n", inet_ntoa(c_addr.sin_addr)); //새로운 스레드를 생성해서 클라이언트의 요청을 처리한다. HANDLE hThread = CreateThread(0 , 0, FileServer, (void *)c_s, 0,0); CloseHandle(hThread); } //--------------------------------------------------------------------------- closesocket(s); // 소켓 닫기 //-------------------------------------------------------------- //------------------------------------------ WSACleanup(); }
//client
#define WIN32_LEAN_AND_MEAN #include<winsock2.h> #include<windows.h> #include<commctrl.h> #include<stdio.h> #pragma comment(lib, "ws2_32.lib") struct FILE_INFO { char FileName[260]; int size; }; FILE_INFO g_info; LRESULT CALLBACK WndProc(HWND hwnd,UINT iMessage,WPARAM wParam,LPARAM lParam); DWORD WINAPI FileClient(void * p) { HWND hwnd = (HWND)p; WSADATA w; WSAStartup(MAKEWORD(2,2), &w); SOCKET s = socket( AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addr; addr.sin_family = AF_INET; addr.sin_port = htons(5000); addr.sin_addr.s_addr = inet_addr("61.81.99.138"); if ( connect(s, (SOCKADDR *)&addr, sizeof(addr)) == -1) { MessageBox( 0, "Connect Error !!","",MB_OK); return 0; } //------------------------------------------------------------- // 파일 정보를 수신한다. recv(s ,(char *)&g_info, sizeof(g_info), 0); //주 스레드에 알려준다. -> 주스레드가 UI를 업데이트 한다.! PostMessage(hwnd, WM_USER+100,0,0); //------------------------------------------------------------- char name[260]; strcpy(name, g_info.FileName); strcat(g_info.FileName, "_bak"); HANDLE hFile = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); int total = g_info.size; int current = 0; char buf[4096]; while(total > current) { int nRecv = recv(s, buf, 4096, 0); if( nRecv <= 0)break; DWORD len; WriteFile(hFile, buf, nRecv, &len, 0); current += nRecv; PostMessage(hwnd, WM_USER+200,0,(LPARAM)current); //------------------------------------------------------------ } if(total != current) MessageBox(0,"Error","",MB_OK); else MessageBox(0,"OK","",MB_OK); closesocket(s); CloseHandle(hFile); WSACleanup(); return 0; } TCHAR lpszClass[] = TEXT("first"); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmdLine, int nShowCmd) { //AllocConsole(); // 콘솔창 생성 //freopen("CONOUT$", //콘솔을 // "wt", //text write모드로 // stdout); //stdoutrhk 연결 MSG Message; //1. 위도우 클래스 만들기 (10가지를 다 정확히 입력하지 않으면 화면이 뜨지 않는다.) WNDCLASS wc; //미리정의된 10개 항목을 채우는 클래스 (WNDCLASSEX 12개 항목 10개 항목에 작은 아이콘, 구조체 크기를 포함한다.) wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH); wc.hCursor = LoadCursor ( 0, IDC_CROSS); wc.hIcon = LoadIcon ( 0, IDI_WINLOGO ); wc.hInstance = hInstance; wc.lpfnWndProc = WndProc; //<~ 이부분을 자신이 만드는 함수로 바꿔줘야 한다. 메시지 함수등록 wc.lpszClassName= lpszClass; wc.lpszMenuName = 0; wc.style = 0; //2. 윈도우 클래스 등록하기. RegisterClass( & wc ); // 등록을 하는 함수도 2가지가 있다. RegisterClass와 RegisterClassEx가 있다. //WNDCLASS로 만들었으면 RegisterClass로 등록하고 WNDCLASSEX로 만들었으면 RegisterClassEx로 등록 //3. 등록된 클래스를 사용해서 윈도우 만들기. // typedef long HWND; // 윈도우의 번호를 담을때 사용 HWND hwnd = CreateWindowEx(0 , // 확장 윈도우 스타일 lpszClass, // 윈도우 클래스 이름 TEXT("첫시작"), // 창이름 WS_OVERLAPPEDWINDOW, // 기본 Window Styles : & ~ 연산으로 기존스타일 제거하기 // WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, // X,Y,W,H 0, // 부모 윈도우 핸들( 번호 ) 0, // 메뉴 핸들( 번호 ) hInstance, // 인스턴스 핸들 0); // 생성인자.( MDI 만들때 사용 ) //4. 윈도우 보여주기 ShowWindow(hwnd, nShowCmd); while(GetMessage(&Message,0,0,0)) //메시지 큐에 가서 메시지를 꺼내오고 가져온 메시지를 윈도우 클래스에 등록된 메세지 처리함수로 전달한다. { //여기서 메시지를 처리하면 부모뿐 아니라 모든 자식윈도우로 전달되는 메시지도 먼저 처리할 수 있다. TranslateMessage(&Message); if (Message.message == WM_SYSKEYDOWN && Message.wParam == 'X') { PostQuitMessage(0); MessageBox(hwnd, "종료","질문",MB_OK); //SendMessage(hwnd, WM_CLOSE,0,0); continue; } //PreTranslateMessae(&Message); DispatchMessage(&Message);//가져온 메시지를 윈도우 클래스에 등록된 메시지 처리함수로 전달한다. } //MessageBox(0, "이제 알겠죠?","물음",MB_OKCANCEL);//종료되지 않게 하기 위해 return 0; } LRESULT CALLBACK WndProc(HWND hwnd,UINT iMessage,WPARAM wParam,LPARAM lParam) { static HWND hEdit1, hEdit2, hPrg; switch(iMessage){ case WM_DESTROY: PostQuitMessage(0); return 0 ; case WM_CREATE: hEdit1 = CreateWindow("edit","", WS_CHILD | WS_VISIBLE | WS_BORDER,// | WS_VSCROLL | ES_MULTILINE, 10,10,200,20,hwnd,(HMENU)1,0,0); hEdit2 = CreateWindow("edit","", WS_CHILD | WS_VISIBLE | WS_BORDER,// | WS_VSCROLL | ES_MULTILINE, 10,40,200,20,hwnd,(HMENU)2,0,0); hPrg = CreateWindow(PROGRESS_CLASS,"", WS_CHILD | WS_VISIBLE | WS_BORDER | PBS_SMOOTH, 10,70,400,20,hwnd,(HMENU)3,0,0); return 0 ; case WM_USER+100: { SetWindowText(hEdit1, g_info.FileName); char buf[256]; wsprintf(buf, "%d", g_info.size); SetWindowText(hEdit2, buf); //프로그래스 초기화 SendMessage(hPrg , PBM_SETRANGE32, 0, g_info.size); } return 0; case WM_USER+200: { SendMessage(hPrg, PBM_SETPOS,lParam,0); } return 0; case WM_LBUTTONDOWN: { CloseHandle(CreateThread(0, 0, FileClient, (void *)hwnd, 0,0)); } return 0; } //꺼내온 메시지를 처리하지 않은경우 -> 바드시 아래 함수를 처리한다. return(DefWindowProc(hwnd,iMessage,wParam,lParam)); }
반응형
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."