// 클라이언트에게 이미지 파일을 바이너리로 전송하는 함수
bool send_image(int client_sock, const std::string& filepath) {
// [1] 파일 경로가 비어있으면 에러 반환
if (filepath.empty()) {
std::cerr << "[ERROR] send_image: 경로가 비어 있습니다." << std::endl;
return false;
}
// [2] 파일을 바이너리 모드로 열기
FILE* file = fopen(filepath.c_str(), "rb");
if (!file) {
std::cerr << "[ERROR] 파일 열기 실패: " << filepath << std::endl;
return false;
}
// [3] 파일의 전체 크기를 구하기 위해 끝으로 이동
fseek(file, 0, SEEK_END);
int32_t filesize = static_cast<int32_t>(ftell(file)); // 현재 위치 = 파일 크기
rewind(file); // 파일 포인터 처음으로 되돌리기
std::cout << "[INFO] 이미지 크기 (바이트): " << filesize << std::endl;
// [4] 파일 크기를 4바이트 리틀 엔디안 형식으로 분해
uint8_t size_bytes[4];
size_bytes[0] = filesize & 0xFF;
size_bytes[1] = (filesize >> 8) & 0xFF;
size_bytes[2] = (filesize >> 16) & 0xFF;
size_bytes[3] = (filesize >> 24) & 0xFF;
// [5] 먼저 이미지 크기 4바이트 전송
send(client_sock, size_bytes, 4, 0);
// [6] 이미지 데이터 본문 전송 (1024바이트 단위로)
char buffer[1024];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) > 0) {
send(client_sock, buffer, bytes_read, 0);
}
// [7] 파일 닫기 및 성공 메시지
fclose(file);
std::cout << "[INFO] 이미지 전송 완료: " << filepath << std::endl;
return true;
}
✅ 작동 원리 요약
이 함수는 TCP 통신을 통해 서버에서 클라이언트로 이미지를 전송하기 위한 정형화된 프로토콜을 구현한 것입니다. 작동 과정은 다음과 같습니다:
- 파일 경로 검증 및 열기
- filepath가 비어있거나 존재하지 않으면 실패 처리.
- fopen(filepath, "rb")를 통해 이미지 파일을 바이너리 읽기 모드로 엶.
- 이미지 크기 전송 (4바이트)
- ftell을 사용해 이미지 전체 바이트 크기를 구함.
- 이 크기를 4바이트 리틀엔디안 포맷으로 분해.
- 클라이언트는 이 4바이트를 수신하여 몇 바이트를 수신해야 할지 판단함 (receiveImageData()에서 처리됨).
- 이미지 데이터 전송
- fread를 사용해 1024바이트씩 읽어와 send로 전송.
- 끝까지 전송되면 종료.
- 정상 종료
- 파일 닫고 로그 출력 후 true 반환.
✅ 이 함수와 클라이언트와의 연동 방식
이 서버 함수는 다음과 같은 클라이언트 구조와 연결되어 있습니다:
- 클라이언트가 JSON으로 show_image 요청 → 서버에서 send_image() 실행
- 클라이언트는 4바이트(파일 크기) → 이어서 바디 데이터 수신 → QImage 변환 → UI에 띄움 (Page4_ShopList::receiveImageData()에서 처리)