在众多大神的帮助下,这个在线播放流媒体服务器终于完成啦。。。。
这个mp3流媒体服务器设计的思路是,服务器程序server用多线程实现和多个客户端的通信(这是必然的),然后发送给客户端当前的音频列表公客户端选择,之后根据k客户端的选择给多个客户端传输相应mp3文件的数据,同时,客户端进行实时地音频解码并播放。
关于libmad开源mp3音频解码库的使用,见上一篇博客吧。。。。
在服务器程序这一端,首先我们要获取当前的音频列表。这里我们用到了glob函数来获取文件的列表。glob() 函数返回匹配指定模式的文件名或目录。 该函数返回一个包含有匹配文件 / 目录的数组。如果出错返回 false。
下面我们在终端中输入 man glob 来看一下glob函数的手册:
int glob(const char *pattern // 文件路径, int flags // 匹配模式,
int (*errfunc) (const char *epath, int eerrno) // 查看错误信息,不需要 则为NULL,
glob_t *pglob // 注意是glob变量的指针);
void globfree(glob_t *pglob);
其中,glob_t 变量是一个结构体,在手册中我们即可看到:
glob变量:
// ** 表示列表 (二维数组,可以用for循环查看其元素)
typedef struct {
size_t gl_pathc; /* Count of paths matched so far */ //迄今为止匹配的路径个数
char *gl_pathv; / List of matched pathnames. */ // 匹配的路径列表
size_t gl_offs; /* Slots to reserve in gl_pathv. */
} glob_t;
而使用for循环即可看到文件列表,之后globfree释放空间。
下面是一个简单的例程,可以实现固定路径下mp3文件的列表显示:
#include <stdio.h>
#include <glob.h>
int main(int argc, const char *argv[])
{
glob_t buf;
int i;
glob("/home/gaoyuzhe/music/*.mp3",GLOB_NOSORT, NULL, &buf);
for(i=0; i < buf.gl_pathc; i++)
{
printf("buf.gl_pathv[%d]= %s \n", i, (buf.gl_pathv[i]));
}
globfree(&buf);
return 0;
}
接下来我们进入正题,首先贴出代码:
服务器 server.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <pthread.h>
#include <glob.h>
#include <sys/stat.h>
#include <fcntl.h>
#define MAXSIZE 512
#define BUF_SIZE 4000000 //缓冲区的大小,也就是一次性传输数据的字节数
#define PORT 1234
/*函数声明*/
void *start_routine(void* arg);
void process_client(int connectfd, struct sockaddr_in client_addr);
struct sockaddr_in server_addr,client_addr;
int listenfd = 0,connectfd = 0;
pthread_t thread;
struct ARG{
int connfd;//文件连接描述符
struct sockaddr_in client;//客户端地址信息
};
struct ARG *arg;
struct MUSIC_PLAY{
char content[BUF_SIZE];
int size;
};
int main()
{
//创建套接字
socklen_t cli_addr_size;
listenfd = socket(PF_INET, SOCK_STREAM,0);
if(listenfd &