출처 주소
http://www.sockaddr.com/ExampleSourceCode.html
바로 받기
- 새로 친 코드
변경 내용 - 약간의 한글화 / 0.5% 수정
수행 내용
- TCP/IP 와 HTTP 사용하여 해당 서버에 접속 해당 파일을 받아 오는 내용(1024Bytes)입니다.
- 수행화면
코드 보기
http://www.sockaddr.com/ExampleSourceCode.html
바로 받기
- 새로 친 코드
변경 내용 - 약간의 한글화 / 0.5% 수정
수행 내용
- TCP/IP 와 HTTP 사용하여 해당 서버에 접속 해당 파일을 받아 오는 내용(1024Bytes)입니다.
- 수행화면
코드 보기
/* 저작권 공지 http://www.sockaddr.com/ExampleSourceCode.html http://cakel.tistory.com sock_gethttp.cpp Hyper Text Transfer Protocol (HTTP : 하이터 텍스트 전송 프로토콜) 을 이용하여 파일을 받아서 stdout(화면) 로 인쇄하는 내용입니다. 서버 이름과 전체 경로를 명령줄 인수로 보내고 출력파력될 파일로 연결 됩니다. 이 과정은 stderr 로 출력이 됩니다. 예 sock_gethttp.exe cakel.tistory.com /index.html index.html을 읽어 옵니다. */ #include <stdio.> #include <io.h> #include <fcnl.h> #include <winsock.h> #pragma comment(lib,"ws2_32.lib") // compile 시 ws2_32.lib 파일을 링크 시킵니다. void GetHTTP(LPCSTR lpServerName, LPCSTR lpFileName); // 오류를 출력하는 도우미 매크로 입니다. #define PRINTERROR(s) fprintf(stderr,"\n%s 오류코드 : %d\n",s , WSAGetLastError()) int main(int argc, char* *argv) { // WinSock Version 1.1 의 wsaData 형 자료 생성 WORD wVersionRequested = MAKEWORD(1, 1); WSADATA wsaData; int nRet; // 인수 확인 if (argc != 3) { fprintf(stderr, "\n사용법 : sock_gethttp.exe [서버 이름] [절대 경로]\n"); return 0; } // WinSock.dll 시작하기 nRet = WSAStartup(wVersionRequested, &wsaData); if(nRet) { fprintf(stderr,"\nWSAStartup() : %d\n", nRet); WSACleanup(); return 0; } // WinSock 버전 확인 if(wsaData.wVersion != wVersionRequested) { fprintf(stderr,"\nWinSock Version 이 지원하지 않습니다.\n"); WSACleanup(); return 0; } // "stdout" 스트림(외부로 통신하는 개체 - 보통 stdout은 화면) // 을 binary(이진) mode 로 하여 .jpg .gif 같은 그림 파일에게도 동작하게 만듭니다. _setmode(_fileno(stdout), _O_BINARY); // GetHTTP() 함수를 수행하여 작업을 개시 합니다. GetHTTP(argv[1], argv[2]); // WinSock 를 풉니다. WSACleanup(); return 0; } void GetHTTP(LPCSTR lpServerName, LPCSTR lpFileName) { // inet_addr() 함수로 서버 주소를 다루는지 아니면 IP 주소인지 확인 합니다. IN_ADDR iaHost; LPHOSTENT lpHostEntry; iaHost.s_addr = inet_addr(lpServerName); if(iaHost.s_addr == INADDR_NONE) { // IP 주소가 아니므로 도메인 이름으로 호스트 주소를 받습니다. lpHostEntry = gethostbyname(lpServerName); } else { // 유효한 IP 주소이므로 호스트 주소를 IP 주소를 통해 받습니다. lpHostEntry = gethostbyaddr( (const char *)&iaHost, sizeof(struct in_addr), AF_INET); } if (lpHostEntry == NULL) { PRINTERROR("함수 gethostbyname() 호출 하는 중에 문제가 발생했습니다."); return; } // TCP/IP stream socket (스트림 소켓 를 생성합니다. SOCKET Socket; // socket(인터넷 주소, 스트림 소켓 형식, TCP 인터넷 프로토콜) Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (Socket == INVALID_SOCKET) { PRINTERROR("socket() 함수를 호출 하는 중에 문제가 발생했습니다."); closesocket(Socket); return; } // TCP 를 통한 HTTP service 를 관장하는 포트 번호를 찾습니다. LPSERVENT lpServEnt; SOCKADDR_IN saServer; lpServEnt = getservbyname("http", "tcp"); if(lpServEnt == NULL) // 찻질 못했으면 기본값인 80번을 받습니다. saServer.sin_port = htons(80); else saServer.sin_port = lpServEnt->s_port; // 서버의 남은 주소 구조체를 완성 합니다. saServer.sin_family = AF_INET; saServer.sin_addr = *( (LPIN_ADDR) *lpHostEntry->h_addr_list); // Socket(소켓)에 접속합니다. int nRet; // connect(접속할 소켓, 소켓에 해당하는 주소의 주소(구조체), 주소 구조체의 길이) nRet = connect(Socket, (LPSOCKADDR)&saServer, sizeof(SOCKADDR_IN) ); if (nRet == SOCKET_ERROR) { PRINTERROR("connect() 함수를 호출하는데 문제가 발생했습니다."); closesocket(Socket); return; } // HTTP 요구를 하는 형식을 정합니다. char szBuffer[1024]; // GET [파일명] : HTTP - 파일을 받습니다. sprintf(szBuffer, "GET %s\n", lpFileName); // send(소켓명, 전송할 버퍼, 버퍼의 길이, 플래그) nRet = send(Socket, szBuffer, strlen(szBuffer), 0); // 파일의 내용을 받아서 stdout 스트림으로 출력합니다. while(1) { // 받을때 까지 기다립니다. nRet = 받은 바이트의 길이 // recv(소켓명, 저장할 퍼버, 버퍼의 길이, 플래그) nRet = recv(Socket, szBuffer, sizeof(szBuffer), 0); if (nRet == SOCKET_ERROR) { PRINTERROR("recv() 함수를 호출하는데 문제가 발생했습니다."); break; } fprintf(stderr,"\nrecv() 함수를 수행하여 %d 바이트틑 보냅니다.\n",nRet); // 서버가 연결을 닫았습니까? if(nRet == 0) break; // stdout 스트림 개체로 출력합니다. fwrite(szBuffer, nRet, 1, stdout); } closesocket(Socket); return; }
Posted by 카켈