一、mediasoup之router的创建过程

        每一个worker代表一个nodejs主进程,通过nodejs的spawn 方法创建一个c++子进程,主进程与子进程之间通过unix socket进行通信,nodejs代码中的channel就是对unix socket的一个封装。

      通过channel的request方法发送 “worker.createRouter”指令,并附加参数routerId,到c++子进程,查看worker.ts代码的createRouter方法:

const internal = { routerId: uuidv4() };

await this.#channel.request('worker.createRouter', internal);

        channel的request方法中把指令包装为{ id, method, internal, data } 的JSON格式的数据,

id:请求id.每次请求递增

method: 即为“worker.createRouter”指令

internal: 此处为 {routerId}

data: 此处为null

然后通过producerSocket发送给c++层面,看如下代码:

/**
	 * @private
	 */
	async request(method: string, internal?: object, data?: any): Promise<any>
	{
		this.#nextId < 4294967295 ? ++this.#nextId : (this.#nextId = 1);

		const id = this.#nextId;

		logger.debug('request() [method:%s, id:%s]', method, id);

		if (this.#closed)
			throw new InvalidStateError('Channel closed');

		const request = { id, method, internal, data };
		const payload = JSON.stringify(request);

		if (Buffer.byteLength(payload) > MESSAGE_MAX_LEN)
			throw new Error('Channel request too big');

		// This may throw if closed or remote side ended.
		this.#producerSocket.write(
			Buffer.from(Uint32Array.of(Buffer.byteLength(payload)).buffer));
		this.#producerSocket.write(payload);
        ........后面省略   
    }

        在c++层面ChannelRequest.cpp代码中,定义了指令到方法id之间的映射关系std::unordered_map:

	std::unordered_map<std::string, ChannelRequest::MethodId> ChannelRequest::string2MethodId =
	{
		{ "worker.close",                                ChannelRequest::MethodId::WORKER_CLOSE                                     },
..................
		{ "worker.createRouter",                         ChannelRequest::MethodId::WORKER_CREATE_ROUTER  
......................
}

从中可以看出createRouter对应的方法MethodId为  ChannelRequest::MethodId::WORKER_CREATE_ROUTER 。我们再看一下MethodId的定义如下,可以看出WORKER_CREATE_ROUTER的值为 5 :

class ChannelRequest
{
	public:
		enum class MethodId
		{
			WORKER_CLOSE = 1,
			WORKER_DUMP,
			WORKER_GET_RESOURCE_USAGE,
			WORKER_UPDATE_SETTINGS,
			WORKER_CREATE_ROUTER,
            ................
        }
};

C++层面在void ConsumerSocket::UserOnUnixStreamRead()中收到消息时,在子类方法ChannelSocket::OnConsumerSocketMessage中对JOSN格式的消息进行解析,并创建ChannelRequest::ChannelRequest类实例,实例中就包含了解析后的{ id, method, internal, data }数据,看下ChannelRequest的成员变量:

	public:
		// Passed by argument.
		Channel::ChannelSocket* channel{ nullptr };
		uint32_t id{ 0u }; 
		std::string method;
		MethodId methodId;
		json internal;
		json data;
		// Others.
		bool replied{ false };

        最后通过c++层面的 Worker::OnChannelRequest对消息进行处理:

inline void Worker::OnChannelRequest(Channel::ChannelSocket* /*channel*/, Channel::ChannelRequest* request)
{
    switch (request->methodId)
	{
        ....................
        case Channel::ChannelRequest::MethodId::WORKER_CREATE_ROUTER:
		{
			std::string routerId;

			try
			{
				SetNewRouterIdFromInternal(request->internal, routerId);
			}
			catch (const MediaSoupError& error)
			{
				MS_THROW_ERROR("%s [method:%s]", error.buffer, request->method.c_str());
			}

			auto* router = new RTC::Router(routerId);

			this->mapRouters[routerId] = router;

			MS_DEBUG_DEV("Router created [routerId:%s]", routerId.c_str());

			request->Accept();

			break;
		}
        ...........................
    }
// Any other request must be delivered to the corresponding Router.
	default:
		{
			try
			{
				RTC::Router* router = GetRouterFromInternal(request->internal);

				router->HandleRequest(request);
			}
			catch (const MediaSoupTypeError& error)
			{
				MS_THROW_TYPE_ERROR("%s [method:%s]", error.buffer, request->method.c_str());
			}
			catch (const MediaSoupError& error)
			{
				MS_THROW_ERROR("%s [method:%s]", error.buffer, request->method.c_str());
			}

			break;
		}
}

其中我们看到了 auto* router = new RTC::Router(routerId); 即是创建了一个router. 

最后通过调用request->Accept(); 向nodejs主进程发送响应消息:

void ChannelRequest::Accept()
{
		MS_TRACE();

		MS_ASSERT(!this->replied, "request already replied");

		this->replied = true;

		json jsonResponse = json::object();

		jsonResponse["id"]       = this->id;
		jsonResponse["accepted"] = true;

		this->channel->Send(jsonResponse);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Mediasoup 的架构分为两部分:客户端和服务端。 1. 客户端:客户端是指使用 Mediasoup 的应用程序或浏览器,客户端需要通过 WebRTC 技术与 Mediasoup 服务器建立连接,并且通过 Mediasoup 提供的 API 来控制和管理媒体流的传输。 2. 服务端:服务端是指运行 Mediasoup 服务器的计算机或虚拟机,服务端需要提供一组 API 和工具,让客户端可以控制和管理 Mediasoup 服务器的媒体流。 Mediasoup 的服务端架构主要由以下几个组件组成: 1. Mediasoup RouterMediasoup RouterMediasoup 的核心组件,它负责管理和控制所有的媒体流。每个 Mediasoup Router 都有一个唯一的 ID,并且可以包含多个 Mediasoup Transport 和 Mediasoup Producer/Consumer。 2. Mediasoup Transport:Mediasoup Transport 是 Mediasoup 的核心组件之一,它负责管理媒体流的传输。每个 Mediasoup Transport 都与 Mediasoup Router 相关联,并且可以被多个 Mediasoup Producer/Consumer 共享。 3. Mediasoup Producer/Consumer:Mediasoup Producer/Consumer 是 Mediasoup 的核心组件之一,它负责生产和消费媒体流。每个 Mediasoup Producer/Consumer 都与 Mediasoup Transport 相关联,并且可以被多个客户端共享。 4. Mediasoup Worker:Mediasoup Worker 是 Mediasoup 的工作线程,它负责处理和转发媒体流。每个 Mediasoup Worker 都可以处理多个 Mediasoup Router。 总之,Mediasoup 的架构非常灵活和可扩展,可以轻松地处理大规模的媒体流,并且提供了强大的 API 和工具,使得开发者可以轻松地构建出高质量的实时通信应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值