前言
一百年没有更新博客了,都怪开学一堆杂活(x
那就顺手把实验报告转到这边吧owo
本实验为SZU原创实验,实验开发团队的老师和助教们都很有耐心。。大赞,环境没配好去群里问是秒回的
相关资料:
实验文档:计算机网络课程综合实验平台 (snrc.site)
一、实验介绍
该实验主要实现了一个服务端和一个客户端。其中,服务端利用缓冲区逐段向客户端发送多个视频片段,并在客户端逐段接收,并利用已经设计好的播放器,在网页中播放连续的视频。
二、实验过程
0. 环境搭建
实验文件中包含了压缩包exp1-lib.zip,exp-code.zip,cne.zip
将其解压,并把前两个压缩包(exp1-lib.zip和exp-code.zip)解压后的文件置于一个目录下,于cne.zip解压出来的文件夹devcpp6中的devcppPortable.exe中打开client.c和server.c文件,选择编译环境为Computer-networks
1. 单文件视频传输
阅读代码发现实验文件中已经实现了:
1)服务端的初始化阶段,包括创建套接字,绑定套接字和监听套接字,以及接收客户端下载请求和发送文件大小给客户端,发送文件结束符和关闭文件。
2)客户端的初始化阶段,向服务器请求文件并接受文件的大小,检查文件结束符后将接收到的视频写入文件中
我们需要实现的是:
1)在服务端:
将文件的内容循环读取到缓冲区中,再将缓冲区的内容发送给客户端,注意读到文件末尾可能无法完整填充整个缓冲区,需要做特判
// 发送视频片段
int send_count = 0;
while (send_count < file_size)
{
/***************************************************************************************************/
/************************** 任务1: 发送指定视频文件(按照固定大小buffer方式) ********************/
/***************************************************************************************************/
char buffer[BUFFER_SIZE] = {0};
int bytes_read = (send_count + BUFFER_SIZE <= file_size) ? BUFFER_SIZE : file_size - send_count;
fread(buffer, bytes_read, 1, fp);
bytes_sent = send(new_socket, buffer, bytes_read, 0);
if (bytes_sent < 0)
printf("ERROR in send video\n");
send_count += bytes_sent;
printf("video send progress: %d / %d\n", send_count, file_size);
}
2)在客户端:
接收服务端发送的数据并写入文件。文件末尾无法完整填充缓冲区的处理方式同服务端
int recv_count = 0;
while (recv_count < file_size)
{
/************************************************************************/
/***************** 任务3 : 如何使用buffer接收视频文件?*****************/
/************************************************************************/
bytes_recv = (recv_count + BUFFER_SIZE <= file_size) ? BUFFER_SIZE : file_size - recv_count;
bytes_recv = recv(sock, video_segement + recv_count, bytes_recv, 0);
recv_count += bytes_recv;
printf("%s recv progress: %d / %d\n", req, recv_count, file_size);
}
2. 实现流式视频传输
实现流式视频传输要求我们在客户端请求同一个视频的多个视频段,那就利用sprintf将指定视频名(包括视频名称-视频分辨率-视频码率)与视频段序号拼接在一起,在客户端循环请求并接收,在服务端循环发送。最后再在客户端调用player.h中设计好的函数,在网页中播放视频
在客户端:
调用StartStreamingServer() 初始化播放器等资源,在循环中利用sprintf构造请求的文件名
StartStreamingServer();
for (int id = 0;id < 60; ++id){
// 发送下载请求
int bytes_sent = 0;
unsigned char s_stop_byte = 0xFF;
// 视频文件名
char req[REQUEST_SIZE] = "";
/******************************************************************/
/***************** 任务2:如何按顺序选择视频文件?*****************/
/******************************************************************/
sprintf(req, "ocean-1080p-8000k-%d.ts", id);
bytes_sent = send(sock, req, REQUEST_SIZE, 0);
if (bytes_sent < 0)
printf("ERROR in send\n");
bytes_sent = send(sock, &s_stop_byte, sizeof(s_stop_byte), 0);
if (bytes_sent < 0)
printf("ERROR in send\n");
printf("send req: %s\n", req);
接收完成时调用ReceiveSegment()将完整的视频段交付给播放器,等待播放
在结束阶段调用WaitEnd()等待视频播放完毕后关闭播放器
/***数据接收完成阶段***/
ReceiveSegment(video_segement, req, file_size);
// 释放内存
free(video_segement);
video_segement = NULL;
}
/*************************************************************************************/
/*********任务2(扩展):如何在视频流传输完成后,通知server结束视频传输?*************/
/*************************************************************************************/
/***结束阶段***/
closesocket(sock);
WSACleanup();
WaitEnd();
}
三、实验结果
先编译运行server.c,服务端启动监听,如下
Create Server Socket Success.
Server Bind Port Success.
Server Listening.....
后编译运行client.c,开始依次传输视频文件
ocean-1080p-8000k-59.ts recv progress: 178176 / 181608
ocean-1080p-8000k-59.ts recv progress: 179200 / 181608
ocean-1080p-8000k-59.ts recv progress: 180224 / 181608
ocean-1080p-8000k-59.ts recv progress: 181248 / *181608*
ocean-1080p-8000k-59.ts recv progress: 181608 / 181608
file_path .\download\ocean-1080p-8000k-59.ts
网页播放视频如下:
帅帅帅
(其实还有思考题,找时间再研究下
标签:视频,文件,流式,计算机网络,send,SZU,recv,服务端,客户端 From: https://blog.csdn.net/andrew_1219/article/details/136858525