네트워크
[네트워크] 프로토콜 적용 파일 클라
program-yam
2025. 4. 22. 14:37
프로토콜이 적용된 파일 클라를 작성해보자.
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을 동적할당 받은 메모리에 쓰고 서버로 전송한다.
이후 서버로부터 파일 정보를 헤더로 받고, 파일을 서버로부터 수신한다.