Creates a new virtual channel.
id is not passed, this creates a virtual channel from scratch. Before
it's used, its VirtualChannel.id must be sent to the remote endpoint
where virtualChannel should be called with that id.
id is passed, this creates a virtual channel corresponding to the
channel with that id on the remote channel.
Throws an ArgumentError if a virtual channel already exists for
Throws a StateError if the underlying channel is closed.
VirtualChannel<T> virtualChannel([int? id]);