프로토콜이 적용된 파일 클라를 작성해보자.
if (::connect(hSocket,
	(SOCKADDR*)&svraddr, sizeof(svraddr)) == SOCKET_ERROR)
{
	ErrorHandler("서버에 연결할 수 없습니다.");
}		
//서버로부터 파일 리스트를 수신한다.
GetFileList(hSocket);
//전송받을 파일을 선택하고 수신한다.
GetFile(hSocket);
클라에서는 서버와 연결이 성공하면 서버로부터 파일 목록을 수신하고,
파일을 선택하여 서버로부터 파일을 수신한다.
GetFileList
void GetFileList(SOCKET hSocket)
{
    //서버에 파일 리스트를 요청한다.
    MYCMD cmd = { CMD_GET_LIST, 0 };
    ::send(hSocket, (const char*)&cmd, sizeof(cmd), 0);
    //서버로부터 파일 리스트를 수신한다.
    ::recv(hSocket, (char*)&cmd, sizeof(cmd), 0);
    if (cmd.nCode != CMD_SND_FILELIST)
    {
        ErrorHandler("서버에서 파일 리스트를 수신하지 못했습니다.");
    }		
    SEND_FILELIST filelist;
    ::recv(hSocket, (char*)&filelist, sizeof(filelist), 0);
    //수신한 리스트 정보를 화면에 출력한다.
    FILEINFO fInfo;
    for (unsigned int i = 0; i < filelist.nCount; ++i)
    {
        ::recv(hSocket, (char*)&fInfo, sizeof(fInfo), 0);
        printf("%d\t%s\t%d\n",
            fInfo.nIndex, fInfo.szFileName, fInfo.dwFileSize);
    }
}
서버에 파일 목록을 수신받는다.
GetFile
void GetFile(SOCKET hSocket)
{
    int nIndex;
    printf("수신할 파일의 인덱스(0~2)를 입력하세요.: ");
    fflush(stdin);
    scanf_s("%d", &nIndex);
    //1. 서버에 파일 전송을 요청
    BYTE *pCommand = new BYTE[sizeof(MYCMD) + sizeof(GETFILE)];
    memset(pCommand, 0, sizeof(MYCMD)+sizeof(GETFILE));
    MYCMD *pCmd = (MYCMD*)pCommand;
    pCmd->nCode = CMD_GET_FILE;
    pCmd->nSize = sizeof(GETFILE);
    GETFILE *pFile = (GETFILE*)(pCommand + sizeof(MYCMD));
    pFile->nIndex = nIndex;
    //두 헤더를 한 메모리에 묶어서 전송한다!
    ::send(hSocket,
        (const char*)pCommand, sizeof(MYCMD) + sizeof(GETFILE), 0);
    delete [] pCommand;
    //2. 전송받을 파일에 대한 상세 정보 수신.
    MYCMD cmd = { 0 };
    FILEINFO fInfo = { 0 };
    ::recv(hSocket, (char*)&cmd, sizeof(cmd), 0);
    if (cmd.nCode == CMD_ERROR)
    {
        ERRORDATA err = { 0 };
        ::recv(hSocket, (char*)&err, sizeof(err), 0);
        ErrorHandler(err.szDesc);
    }
    else
    {
        ::recv(hSocket, (char*)&fInfo, sizeof(fInfo), 0);    
    }
		
    //3. 파일을 수신한다.
    printf("%s 파일 수신을 시작합니다!\n", fInfo.szFileName);
    FILE *fp = NULL;
    errno_t nResult = fopen_s(&fp, fInfo.szFileName, "wb");
    if (nResult != 0)
    {
        ErrorHandler("파일을 생성 할 수 없습니다.");
    }		
    char byBuffer[65536]; //64KB
    int nRecv;
    DWORD dwTotalRecv = 0;
    while ((nRecv = ::recv(hSocket, byBuffer, 65536, 0)) > 0)
    {
        fwrite(byBuffer, nRecv, 1, fp);
        dwTotalRecv += nRecv;
        putchar('#');
        if (dwTotalRecv >= fInfo.dwFileSize)
        {
            putchar('\n');
            puts("파일 수신완료!");
            break;
        }
    }
    fclose(fp);
}
서버로부터 받은 파일 목록 중에서 원하는 파일을 선택하고,
기본 헤더와 CMD_GET_FILE을 동적할당 받은 메모리에 쓰고 서버로 전송한다.
이후 서버로부터 파일 정보를 헤더로 받고, 파일을 서버로부터 수신한다.
'네트워크' 카테고리의 다른 글
| [네트워크] UDP (0) | 2025.04.22 | 
|---|---|
| [네트워크] 소켓 (0) | 2025.04.22 | 
| [네트워크] 프로토콜 적용 파일 서버 (0) | 2025.04.22 | 
| [네트워크] 프로토콜이 적용된 파일 송/수신 (0) | 2025.04.22 | 
| [네트워크] 파일 수신 ( TransmitFile ) (0) | 2025.04.21 | 

