본문 바로가기

카테고리 없음

c++로 서버 만들어서 파일 보내기

#include <iostream>

#include <fstream>

#include <cstring>

#include <sstream>

#include <sys/socket.h>

#include <netinet/in.h>

#include <unistd.h>

#include <sys/stat.h>

 

int main() {

    // 1. 서버 소켓 생성 및 옵션 설정

    int server_fd = socket(AF_INET, SOCK_STREAM, 0);

    if (server_fd == -1) {

        perror("소켓 생성 실패");

        return -1;

    }

    int opt = 1;

    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {

        perror("옵션 설정 실패");

        return -1;

    }

 

    // 2. 서버 주소 설정 (모든 인터페이스, 포트 8080)

    sockaddr_in address;

    address.sin_family = AF_INET;

    address.sin_addr.s_addr = INADDR_ANY;

    address.sin_port = htons(8080);

 

    if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {

        perror("바인딩 실패");

        return -1;

    }

 

    if (listen(server_fd, 3) < 0) {

        perror("리스닝 실패");

        return -1;

    }

    std::cout << "HTTP 서버가 포트 8080에서 대기 중입니다.\n";

 

    while (true) {

        // 3. 클라이언트 연결 수락

        int addrlen = sizeof(address);

        int client_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);

        if (client_socket < 0) {

            perror("연결 수락 실패");

            continue;

        }

        std::cout << "클라이언트 연결됨.\n";

 

        // 4. HTTP 요청 읽기 (여기서는 요청 내용을 간단히 읽어 출력)

        char request_buffer[1024] = {0};

        read(client_socket, request_buffer, sizeof(request_buffer) - 1);

        std::cout << "요청 내용:\n" << request_buffer << "\n";

 

        // 5. 전송할 파일 열기

        const char* filename = "/Users/yeongjae/Desktop/y_downloader/y_downloader/myproject.unitypackage";

        std::ifstream file(filename, std::ios::binary);

        if (!file) {

            std::string not_found = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";

            send(client_socket, not_found.c_str(), not_found.size(), 0);

            close(client_socket);

            continue;

        }

 

        // 6. 파일 크기 구하기

        struct stat file_stat;

        if (stat(filename, &file_stat) < 0) {

            perror("파일 상태 확인 실패");

            close(client_socket);

            continue;

        }

        off_t file_size = file_stat.st_size;

 

        // 7. HTTP 응답 헤더 구성

        std::stringstream header;

        header << "HTTP/1.1 200 OK\r\n";

        header << "Content-Type: application/octet-stream\r\n";

        header << "Content-Disposition: attachment; filename=\"" << filename << "\"\r\n";

        header << "Content-Length: " << file_size << "\r\n";

        header << "Connection: close\r\n\r\n";

        std::string header_str = header.str();

 

        // 8. 응답 헤더 전송

        send(client_socket, header_str.c_str(), header_str.size(), 0);

 

        // 9. 파일 데이터를 청크 단위(예: 4096바이트)로 읽어 전송

        const size_t buffer_size = 4096;

        char buffer[buffer_size];

        while (file) {

            file.read(buffer, buffer_size);

            std::streamsize bytes_read = file.gcount();

            if (bytes_read > 0) {

                size_t total_sent = 0;

                while (total_sent < static_cast<size_t>(bytes_read)) {

                    ssize_t sent = send(client_socket, buffer + total_sent, bytes_read - total_sent, 0);

                    if (sent < 0) {

                        perror("데이터 전송 오류");

                        break;

                    }

                    total_sent += sent;

                }

            }

        }

 

        std::cout << "파일 전송 완료.\n";

        file.close();

        close(client_socket);

    }

 

    close(server_fd);

    return 0;

}

 

이 컴퓨터에 있는 파일을 다른 컴퓨터로 보내고싶었는데 크기가 커서 메일이나 클라우드에 올리고 받기 시간이 아까웠다.

 

블루투스도 맘에 안들고 하나는 맥북이고 하나는 우분투라 에어드랍도 안된다.

 

 직접 전송할 수 있게 하면 문제를 해결할 것 같았다.

 

그래서 나에게 익숙한 C++로 서버를 만들어서 파일을 보내기로 했다.

 

filename에 파일을 적어두고 빌드해서 실행하고

웹클라이언트로 서버의 8080포트로 접속하면 다운로드 받을 수 있다.