I am practicing UDP socket programming. My code's functions are below.
Transfer video file to client is working. But it is written in binary so I can't open the video.
So I try to use ffmpeg to convert the video, but it doesn't work.
Is there something wrong in my code? How can I transfer a received file to a video file?
My environment is MacOs.
Server.c (Server Code):
#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 (Client code)
#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;
}
I try to convert the binary file to an .mp4
file using ffmpeg
but it doesn't work:
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
On the server side, you are not sending the video file's bytes to the client at all (you commented out that code), you are instead sending the size
variable over and over, thus your client is saving a file that is just full of buffer sizes, which is why ffmpeg can't convert the data.
Also, your server is closing the video file after the 1st loop iteration, so subsequent loop iterations can't read from the file anymore (not that it matters since you are not doing any error handling on your file reads).