#本文实现了使用UDP协议传输MP3文件
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
/*******************************************************************
*
* file name: music_server.c
* author : j_howe@163.com
* date : 2024/6/10
* function : 通过UDP协议从服务器中下载MP3音频文件
* note : 使用该.c文件时应确保服务器处于运行态
*
* CopyRight (c) 2023-2024 j_howe@163.com All Right Reseverd
*
* *****************************************************************/
#define MP3_PATH "./leave.mp3"
int main()
{
// 1.创建UDP套接字
int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (udp_socket == -1)
{
fprintf(stderr, "udp socket error,errno:%d,%s\n", errno, strerror(errno));
exit(1);
}
// 2.服务器绑定本地的端口和IP地址
struct sockaddr_in host_addr;
host_addr.sin_family = AF_INET; // 协议族,是固定的
host_addr.sin_port = htons(atoi("60000")); // 目标端口,必须转换为网络字节序
host_addr.sin_addr.s_addr = INADDR_ANY; // 目标地址 "192.168.64.xxx" 已经转换为网络字节序 INADDR_ANY
bind(udp_socket, (struct sockaddr *)&host_addr, sizeof(host_addr));
struct sockaddr_in client;
socklen_t client_len = sizeof(client);
// 3.等待客户端发送请求
char recvbuf[64];
char sendbuf[512];
while (1)
{
recvfrom(udp_socket, recvbuf, sizeof(recvbuf), 0, (struct sockaddr *)&client, &client_len);
if (strstr(recvbuf, "download"))
{
FILE *fp = fopen(MP3_PATH, "rb");
struct stat mp3_file;
stat(MP3_PATH, &mp3_file);
int mp3_size = mp3_file.st_size;
// 判断循环次数->需要发送多少次512字节
int num = mp3_size / 512;
int remainder = mp3_size % 512;
if (remainder > 0)
{
num++;
}
printf("num = %d\n", num);
int cnt = 0;
for (int i = 0; i < num; i++)
{
fread(sendbuf, 1, 512, fp);
sendto(udp_socket, sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&client, client_len);
usleep(2000);
printf("cnt = %d\n", cnt++);
bzero(sendbuf, 512);
}
sendto(udp_socket, "over", 5, 0, (struct sockaddr *)&client, client_len);
printf("123456\n");
fclose(fp);
}
}
return 0;
}
/*******************************************************************
*
* file name: music_server.c
* author : j_howe@163.com
* date : 2024/6/10
* function : 指定用户需要下载文件路径,提供下载资源
* note : 本文件优先于客户端运行
*
* CopyRight (c) 2023-2024 j_howe@163.com All Right Reseverd
*
* *****************************************************************/
#define MP3_PATH "./leave.mp3"
int main()
{
// 1.创建UDP套接字
int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (udp_socket == -1)
{
fprintf(stderr, "udp socket error,errno:%d,%s\n", errno, strerror(errno));
exit(1);
}
// 2.服务器绑定本地的端口和IP地址
struct sockaddr_in host_addr;
host_addr.sin_family = AF_INET; // 协议族,是固定的
host_addr.sin_port = htons(atoi("60000")); // 目标端口,必须转换为网络字节序
host_addr.sin_addr.s_addr = INADDR_ANY; // 目标地址 "192.168.64.xxx" 已经转换为网络字节序 INADDR_ANY
bind(udp_socket, (struct sockaddr *)&host_addr, sizeof(host_addr));
struct sockaddr_in client;
socklen_t client_len = sizeof(client);
// 3.等待客户端发送请求
char recvbuf[64];
char sendbuf[512];
while (1)
{
recvfrom(udp_socket, recvbuf, sizeof(recvbuf), 0, (struct sockaddr *)&client, &client_len);
if (strstr(recvbuf, "download"))
{
FILE *fp = fopen(MP3_PATH, "rb");
struct stat mp3_file;
stat(MP3_PATH, &mp3_file);
int mp3_size = mp3_file.st_size;
// 判断循环次数->需要发送多少次512字节
int num = mp3_size / 512;
int remainder = mp3_size % 512;
if (remainder > 0)
{
num++;
}
printf("num = %d\n", num);
int cnt = 0;
for (int i = 0; i < num; i++)
{
fread(sendbuf, 1, 512, fp);
sendto(udp_socket, sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&client, client_len);
usleep(2000);
printf("cnt = %d\n", cnt++);
bzero(sendbuf, 512);
}
sendto(udp_socket, "over", 5, 0, (struct sockaddr *)&client, client_len);
printf("123456\n");
fclose(fp);
}
}
return 0;
}