(Программирование сокетов C_UDP) Как преобразовать двоичный файл в видеоформат?

Я занимаюсь программированием сокетов UDP. Функции моего кода приведены ниже.

  1. Подключите сервер-клиент и отправьте друг другу сообщение «привет» (оно работает).
  2. Затем Сервер отправляет видеофайл клиенту (проблема).

Передача видеофайла клиенту работает. Но оно записано в двоичном формате, поэтому я не могу открыть видео.

Поэтому я пытаюсь использовать ffmpeg для конвертации видео, но это не работает.

Что-то не так в моем коде? Как перевести полученный файл в видеофайл?

Моя среда — MacOs.

Server.c (Код сервера):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>

#define PORT 8888
#define BUF_SIZE 256

int main(){
    int serv_sock;
    char message[BUF_SIZE];
    char buf[BUF_SIZE];
    int str_len;
    socklen_t clnt_adr_sz;

    struct sockaddr_in serv_adr, clnt_adr;
    
    //create socket
    serv_sock=socket(PF_INET, SOCK_DGRAM, 0);
    if (serv_sock == -1){
        perror("socket() error");
        exit(1);
    }
    
    //socket address
    memset(&serv_adr, 0, sizeof(serv_adr));
    serv_adr.sin_family=AF_INET;
    serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
    serv_adr.sin_port=htons(PORT);
    //binding socket
    if (bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1){
        perror("bind() error");
        exit(1);
    }
    
    while(1){
        clnt_adr_sz=sizeof(clnt_adr);
        str_len=recvfrom(serv_sock, message, BUF_SIZE, 0, (struct sockaddr *)&clnt_adr, &clnt_adr_sz);
         if (str_len < 0) {
            perror("recvfrom error");
            exit(1);
        }
    
        char hello_message[] = "hello i am server";
        if (sendto(serv_sock, hello_message, strlen(hello_message), 0, (struct sockaddr *)&clnt_adr, clnt_adr_sz) < 0) {
            perror("sendto error");
            exit(1);
        }
        
        //print message
        message[str_len] = '\0';
        printf("client say: %s\n", message);
        
        char buf[BUF_SIZE];
        ssize_t bytes_read;
        // sending viedo file
        printf("sending video file...\n");
        size_t fsize;
    
        //video file
        FILE *file;
        char *filename = "video.mp4";
        // open video file
        file = fopen(filename, "rb");
        if (file == NULL) {
            perror("File opening failed");
            exit(EXIT_FAILURE);
        }
        //calculate video file memory
        fseek(file, 0, SEEK_END);
        fsize = ftell(file);
        fseek(file,0,SEEK_SET);
    
        size_t size = htonl(fsize);
        int nsize =0;
        
        while(nsize!=fsize){
            int fpsize = fread(buf,1, BUF_SIZE, file);
            nsize += fpsize;
            if (sendto(serv_sock, &size, sizeof(size), 0, (struct sockaddr *)&clnt_adr, clnt_adr_sz) < 0) {
                perror("sendto");
                exit(EXIT_FAILURE);    
            }
            fclose(file);
            /*
            while ((bytes_read = fread(buf, 1, BUF_SIZE, file)) > 0) {
                if (sendto(serv_sock, buf, bytes_read, 0,
                       (struct sockaddr *)&clnt_adr, clnt_adr_sz) < 0) {
                    perror("sendto");
                    exit(EXIT_FAILURE);
                }       
            }
            */
        }        
    }
    close(serv_sock);
    return 0;
}

Client.c (Код клиента)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>

#define BUFSIZE 256
#define PORT 8888

int main(){
    int sock;
    char message[BUFSIZE];
    int str_len;
    socklen_t adr_sz;

    struct sockaddr_in serv_addr, client_addr;   
    
    sock = socket(PF_INET, SOCK_DGRAM, 0);
    if (sock == -1){
        printf("socket() error\n");
        exit(1);
    }

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    serv_addr.sin_port = htons(PORT);

    char hello_message[] = "hello i am client";
    sendto(sock, hello_message, strlen(hello_message), 0, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    adr_sz = sizeof(client_addr);
    str_len=recvfrom(sock,message,BUFSIZE,0,(struct sockaddr*)&client_addr,&adr_sz);
   
    message[str_len] = '\0';
    printf("client say: %s\n", message);
    
    /*
    char buf[BUFSIZE];
    ssize_t bytes_received;
    socklen_t serv_len = sizeof(serv_addr);
    while ((bytes_received = recvfrom(sock, buf, BUFSIZE, 0,
                                      (struct sockaddr *)&serv_addr, &serv_len)) > 0) {
        fwrite(buf, 1, bytes_received, file);
    }
    */
     
    FILE *file = fopen("received_test.mp4", "wb");

    int nbyte = BUFSIZE;
    while(nbyte>= BUFSIZE){
        nbyte = recvfrom(sock, message, BUFSIZE, 0, (struct sockaddr*)&serv_addr, &adr_sz);
        fwrite(message, sizeof(char), nbyte, file);
    }

    if (file == NULL) {
        perror("File opening failed");
        exit(EXIT_FAILURE);
    }

    fclose(file);
    close(sock);
    printf("File received successfully\n");
    
    return 0;
}

Я пытаюсь преобразовать двоичный файл в файл .mp4 с помощью ffmpeg. но это не работает:

ffmpeg -i received_test.mp4 output.mp4
ffmpeg version 7.0 Copyright (c) 2000-2024 the FFmpeg developers
  built with Apple clang version 15.0.0 (clang-1500.3.9.4)
  configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/7.0 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags='-Wl,-ld_classic' --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d --enable-libharfbuzz --enable-libjxl --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopenvino --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-audiotoolbox --enable-neon
  libavutil      59.  8.100 / 59.  8.100
  libavcodec     61.  3.100 / 61.  3.100
  libavformat    61.  1.100 / 61.  1.100
  libavdevice    61.  1.100 / 61.  1.100
  libavfilter    10.  1.100 / 10.  1.100
  libswscale      8.  1.100 /  8.  1.100
  libswresample   5.  1.100 /  5.  1.100
  libpostproc    58.  1.100 / 58.  1.100
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x12a62bdb0] Format mov,mp4,m4a,3gp,3g2,mj2 detected only with low score of 1, misdetection possible!
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x12a62bdb0] moov atom not found
[in#0 @ 0x12b0043c0] Error opening input: Invalid data found when processing input
Error opening input file received_test.mp4.
Error opening input files: Invalid data found when processing input

UDP не гарантирует доставку. Поскольку вы отправляете так же быстро, как читаете данные, как только какой-либо буфер на пути заполнится и начнет отбрасывать пакеты, вы потеряете данные. Используйте TCP для гарантированной доставки и управления потоком.

stark 30.04.2024 22:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

На стороне сервера вы вообще не отправляете байты видеофайла клиенту (вы закомментировали этот код), вместо этого вы отправляете переменную size снова и снова, таким образом, ваш клиент сохраняет файл, который просто заполнен буфером. размеры, поэтому ffmpeg не может конвертировать данные.

Кроме того, ваш сервер закрывает видеофайл после первой итерации цикла, поэтому последующие итерации цикла больше не могут читать файл (не то, чтобы это имело значение, поскольку вы не выполняете никакой обработки ошибок при чтении файла).

Другие вопросы по теме