一、总结如下几点:
- 通过send函数和recv函数计算发送和接收的总字节数,并通过发送和接收的时间段来计算收发比特率。简单的计算为totalsizes/totaltimeduration。
- 如何封装发送的数据也是有讲究的,可以自定义一个增量算法,让每次发送的测试数据自动增长。
- 每个包发送的时间间隔是否需要设置?这个要看客户端实现,如果是select模型,可以不设置,直到socket出错后重置后继续发送(比如前面介绍的飞秋源码发送文件的实现),有些客户端实现每次send函数中间会sleep一个很小的时间,让sendbuf充分的处理数据后再继续写另一个包的数据,比如sleep个5ms之类的,但测试速度我觉得不合适这么用。
- 发送测试数据的总时间,可以自己定义。
二、srs服务器代码分析
(1)测试带宽函数,收发数据的关键代码如下
int SrsBandwidth::do_bandwidth_check(SrsKbpsLimit* limit)
{
int ret = ERROR_SUCCESS;
SrsBandwidthSample play_sample;
SrsBandwidthSample publish_sample;
// timeout for a packet.
_rtmp->set_send_timeout(play_sample.duration_ms * 1000 * 2);
_rtmp->set_recv_timeout(publish_sample.duration_ms * 1000 * 2);
// start test.
srs_update_system_time_ms();
int64_t start_time = srs_get_system_time_ms();
// sample play
srs_info("start play test.");
if ((ret = play_start(&play_sample, limit)) != ERROR_SUCCESS) {
srs_error("bandwidth play check failed. ret=%d", ret);
return ret;
}
if ((ret = play_checking(&play_sample, limit)) != ERROR_SUCCESS) {
srs_error("bandwidth play check failed. ret=%d", ret);
return ret;
}
if ((ret = play_stop(&play_sample, limit)) != ERROR_SUCCESS) {
srs_error("bandwidth play check failed. ret=%d", ret);
return ret;
}
srs_info("stop play test. kbps=%d", play_sample.kbps);
// sample publish
srs_info("start publish test.");
if ((ret = publish_start(&publish_sample, limit)) != ERROR_SUCCESS) {
srs_error("bandwidth publish check failed. ret=%d", ret);
return ret;
}
if ((ret = publish_checking(&publish_sample, limit)) != ERROR_SUCCESS) {
srs_error("bandwidth publish check failed. ret=%d", ret);
return ret;
}
if ((ret = publish_stop(&publish_sample, limit)) != ERROR_SUCCESS) {
srs_error("bandwidth publish check failed. ret=%d", ret);
return ret;
}
srs_info("stop publish test. kbps=%d", publish_sample.kbps);
// stop test.
srs_update_system_time_ms();
int64_t end_time = srs_get_system_time_ms();
srs_trace("bandwidth ok. duartion=%dms(%d+%d), play=%dkbps, publish=%dkbps",
(int)(end_time - start_time), play_sample.actual_duration_ms,
publish_sample.actual_duration_ms, play_sample.kbps,
publish_sample.kbps);
if ((ret = finial(play_sample, publish_sample, start_time, end_time)) != ERROR_SUCCESS) {
return ret;
}
st_usleep(_SRS_BANDWIDTH_FINAL_WAIT_MS * 1000);
srs_info("BW check finished.");
return ret;
}
解析:
首先服务器发送伪装rtmp packet给客户端,然后根据发送的数据大小和实际持续时间来计算kbps。
然后服务器接收客户端发送回来的伪装rtmp packet数据,计算接收的kbps。
(2)发送数据
int SrsBandwidth::play_checking(SrsBandwidthSample* sample, SrsKbpsLimit* limit)
{
int ret = ERROR_SUCCESS;
// send play data to client
int size = 1024; // TODO: FIXME: magic number
char random_data[size];
memset(random_data, 'A', size);
int data_count = 1;
srs_update_system_time_ms();
int64_t starttime = srs_get_system_time_ms();
while ((srs_get_system_time_ms() - starttime) < sample->duration_ms) {
st_usleep(sample->interval_ms);
// TODO: FIXME: use shared ptr message.
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_playing();
// TODO: FIXME: magic number
for (int i = 0; i < data_count; ++i) {
std::stringstream seq;
seq << i;
std::string play_data = "SRS band check data from server's playing......";
pkt->data->set(seq.str(), SrsAmf0Any::str(play_data.c_str()));
}
data_count += 2;
if ((ret = _rtmp->send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) {
srs_error("send bandwidth check play messages failed. ret=%d", ret);
return ret;
}
limit->send_limit();
}
srs_update_system_time_ms();
sample->calc_kbps(_rtmp->get_send_bytes(), srs_get_system_time_ms() - starttime);
srs_info("BW check send play bytes over.");
return ret;
}
其中:
会先设置一个计划发送持续时间sample->duration_ms(3秒),即while((srs_get_system_time_ms()-starttime) < sample->duration_ms)中的duration_ms。
封装的数据是根据发送包的序列不断增长的。
// TODO: FIXME: magic number
for (int i = 0; i < data_count; ++i) {
std::stringstream seq;
seq << i;
std::string play_data = "SRS band check data from server's playing......";
pkt->data->set(seq.str(), SrsAmf0Any::str(play_data.c_str()));
}
data_count += 2;
(3)包间间隔发送时间,即st_usleep(sample->interval_ms)的休眠时间设置0,如下代码可见interval_ms被初始化为0,后面没有对interval_ms进行改变。
SrsBandwidthSample::SrsBandwidthSample()
{
duration_ms = _SRS_BANDWIDTH_SAMPLE_DURATION_MS;
kbps = interval_ms = actual_duration_ms = bytes = 0;
}
(4)设置了一个速度上限,如果大于 1000kbps的速度,则休息一下(100ms)。代码如下:
#define _SRS_BANDWIDTH_LIMIT_INTERVAL_MS 100
void SrsKbpsLimit::send_limit()
{
_kbps->sample();
while (_kbps->get_send_kbps() > _limit_kbps) {
_kbps->sample();
st_usleep(_SRS_BANDWIDTH_LIMIT_INTERVAL_MS * 1000);
}
}
三、详细请看srs_lib_bandwidth.hpp和srs_lib_bandwidth.cpp这两个文件。
四、最后看看官网的测试速度



本文介绍了如何通过srs服务器进行带宽速度测试。关键在于计算收发数据的字节数和时间,以及自定义数据增长算法。srs服务器的测试带宽函数涉及发送伪装rtmp packet并根据数据大小和时间计算kbps,同时设置了速度上限,超过1000kbps则休息100ms。详细实现可查阅srs_lib_bandwidth.hpp和srs_lib_bandwidth.cpp文件。
277

被折叠的 条评论
为什么被折叠?



