PDA

Просмотр полной версии : RTMFP, обьясните по пальцам!


ashIndie
25.02.2012, 17:52
Здравствуйте. Пытаюсь разобраться с p2p соединением посредством RTMFP.
Естественно перед тем как спросить я не один час провел в гугле прежде чем написать на форум.
И так, что собственно сейчас пытаюсь сделать...
Флешка, в которой есть 2 окошка, в одном показывается видео с камеры пользователя, в другом с камеры подключенного пользователя, тоесть такой приватный как бы чат...
Что понял и сделал:
Получил код разработчика на сайте, создал NetConnection, подключился, создал sendStream, тобишь канал по которому собираюсь передавать видео и звук.
Ну и получил peerID. На этом все. Дальше я закопался в примерах и в конец запутался. Поэтому прошу помощи у вас, товарищи...

вот собственно код:

package {

public class Main extends MovieClip {

private const CIRRUS_ADDRESS:String = "rtmfp://p2p.rtmfp.net";
private const DEVELOPER_KEY:String = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxx";
private var netConnection:NetConnection;
private var myPeerID;
private var farPeerID;
//streams
private var sendStream:NetStream;
private var recvStream:NetStream;
private var video:Video;

var netGroup:NetGroup;
private const GROUP:String = "ashIndie";

public function Main() {
netConnection = new NetConnection();
// Добавляем детектор (listener) для получаения информации о статусе соединения
netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnectionHandler);
// Соединяемся со Cirrus
netConnection.connect(CIRRUS_ADDRESS, DEVELOPER_KEY);
}

function netConnectionHandler(e:NetStatusEvent):void {
if (e.info.code=="NetConnection.Connect.Success") {
trace(e.info.code);
myPeerID = netConnection.nearID;
initSendStream();
}
}

// для отправки потока данных пиру
private function initSendStream() {
trace("initSendStream()");
sendStream = new NetStream(netConnection, NetStream.DIRECT_CONNECTIONS);
sendStream.addEventListener(NetStatusEvent.NET_STATUS, netStreamHandler);
sendStream.publish("media");
sendStream.attachAudio(Microphone.getMicrophone());
sendStream.attachCamera(Camera.getCamera());

var sendStreamClient:Object = new Object();
sendStreamClient.onPeerConnect = function(callers:NetStream):Boolean {
farPeerID = callers.farID;
trace("onPeerConnect "+farPeerID);
return true;
}
sendStream.client = sendStreamClient;
}

private function initRecvStream() {
trace("initRecvStream()");
trace("myPerrID = ", myPeerID);
recvStream = new NetStream(netConnection, myPeerID);
recvStream.addEventListener(NetStatusEvent.NET_STATUS, netStreamHandler);
recvStream.play("media");

video = new Video(320, 240);
video.attachNetStream(recvStream);
addChild(video);

recvStream.client = this;
}

function netStreamHandler(e:NetStatusEvent):void {
trace(e.info.code);
if (e.info.code=="NetStream.Publish.Start") {
initRecvStream();
}
}

}

}


для удобства чтения импорты убрал
Прошу помогите, на самом деле срочно нужно сделать...

Aquahawk
25.02.2012, 17:58
http://labs.adobe.com/technologies/cirrus/samples/
Это превосходный пример на вашу тему. Там всё просто и понятно в исходниках. Сейчас у меня нет возможности поковыряться в вашем случае. И спрячьте ваш developer key. С одной стороны ничего страшного, но и ничего полезного тоже.

ashIndie
25.02.2012, 18:07
Благодарю вас за пример, но к сожалению я его уже пытался копать и не разобрался.
Ключ разработчика спрятал, спасибо за замечание.
Ну может кто еще поможет....
initRecvStream() запускается, но событий с него не получается никаких....может я до конца не понимаю весь механизм обмена peerID или еще чего...
Нужен просто человек который сможет внятно обьяснить....можно по скайпу или аське, можно тут....
я как бы в as не дуб дубом, но просто с NetConnection как-то не доводилось работать....а тут узнал про него, и открываются такие перспективы если понять как он работает....
А вот этот пример мне нужно срочно сделать....
Спасибо большое всем кто ответит или что посоветует....

Добавлено спустя пару минут:
Рассматриваю вариант использования без netgroup, сначала хотя бы просто понять как обмениваться видеопотоками.
насчет этого я вас потом замучаю, хотя оооочень надеюсь что нет.

Silicium
25.02.2012, 18:13
http://melnaron.net/development/peer-to-peer-chat-in-flash

ashIndie
25.02.2012, 18:17
Silicium, спасибо. Видел эту статью, щас попробую изучить ее более детально. Но там обмен Peer ID идет через php&mySQL, это не совсем подходит, так как именно этот обмен без php хочется реализовать...а сам механизм непонятен.
Ну жду еще помощи.

Aquahawk
25.02.2012, 18:17
без netgroup
А в чате один на один нетгруп и не нужен совсем. Это практически два разных механизма взаимодействия с нетгреппой и один на один.

ashIndie
25.02.2012, 18:22
Aquahawk, каким образом тогда они находят друг друга?
правильно ли я указываю видео поток вот таким способом:
video = new Video(320, 240);
video.attachNetStream(recvStream);
addChild(video);

вот этот код мне не понятен, он не срабатывает в принципе:
var sendStreamClient:Object = new Object();
sendStreamClient.onPeerConnect = function(callers:NetStream):Boolean {
farPeerID = callers.farID;
trace("onPeerConnect "+farPeerID);
return true;
}
sendStream.client = sendStreamClient;
а этот не отправляет события никакие:
recvStream = new NetStream(netConnection, myPeerID);
recvStream.addEventListener(NetStatusEvent.NET_STATUS, netStreamHandler);

Silicium
25.02.2012, 18:25
Либо нетгруп, либо свой трекер.

ashIndie
25.02.2012, 18:27
да я не против нетгруп, только не понимаю как это реализуется....

Silicium
25.02.2012, 18:33
да я не против нетгруп
а я против - их использование требует разрешения использовать пиринговые сети.
Так Вы хотите узнать, как реализуется р2р посредством нетгрупп или без, я так и не пойму.

вот этот код мне не понятен, он не срабатывает в принципе:
Он выполняется, когда к Вашему публикующему потоку присоединяются слушаетли

ashIndie
25.02.2012, 18:38
ну а я пытаюсь щас сделать чтобы одно и то же приложение было и отправителем и слушателем....так нельзя?
farPeerID = callers.farID; для чего используется?

MikroAcse
25.02.2012, 18:42
Используйте библиотеку Tom'а Krcha. (http://flashrealtime.com/demos/sharedmovements/P2PGameEngineLibrary.zip)
И там же есть примеры.

Silicium
25.02.2012, 18:44
я пытаюсь щас сделать чтобы одно и то же приложение было и отправителем и слушателем....так нельзя?
Конечно можно, иначе смысла бы в этом не было. Для этого у вас должно существовать как-минимум два потока: один публикующий, другой принимающий. По ссылке, что я привел, все очень подробно разжеванно. Если скачаете исходник, то должно стать еще понятнее.
в краце:
создаете публикующий поток. В его клиенте должен быть определен тот самый метот onPeerConnect, из которого Вы создаете принимающий поток. Ему в конструктор передаете callers.farID, и тогда он начинает (по вызову метода .play(name)) "слушать" оппонента. Вот и все. Отправка идет через публикующий поток, приме - через принимающий.

Добавлено через 41 секунду
Используйте библиотеку Tom'а Krcha.
Она на нетгруппах. Тем более, человек хочет разобраться в механизме.

MikroAcse
25.02.2012, 18:52
Она на нетгруппах.
Если бы на использовала NetGroup, то я бы ней не пользовался, потому что из-за NetGroup P2P стает очень медленным (пинг от 1 секунды).
А у меня пинг меньше 0.2 секунд.

ashIndie
25.02.2012, 19:28
каким образом мне тогда сделать обмен этими ID?
помогите ктонибудь, как мне исправить код чтобы все получилось?....я уже просто целый день сижу и запутался в примерах совсем.....дайте аську, скайп или помогите исправить код....чтобы я наглядно увидел как надо было сделать....примеров достаточно....но под конец дня я уже ничего не понимаю....
очень прошу...))) знающему человеку пару минут потратить, а мне еще день копать....

Silicium
25.02.2012, 19:46
Код выложи - посмотрим.

ashIndie
25.02.2012, 19:56
package {

import flash.display.MovieClip;
import flash.net.NetConnection;
import flash.events.NetStatusEvent;
import flash.net.NetStream;
import flash.media.Microphone;
import flash.media.Camera;
import fl.video.*;
import flash.media.Video;
import flash.net.NetGroup;
import flash.net.GroupSpecifier;


public class Main extends MovieClip {

private const CIRRUS_ADDRESS:String = "rtmfp://p2p.rtmfp.net";
private const DEVELOPER_KEY:String = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
private var netConnection:NetConnection;
private var myPeerID;
private var farPeerID;
//streams
private var sendStream:NetStream;
private var recvStream:NetStream;
private var video:Video;

public function Main() {
netConnection = new NetConnection();
// Добавляем детектор (listener) для получаения информации о статусе соединения
netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnectionHandler);
// Соединяемся со Cirrus
netConnection.connect(CIRRUS_ADDRESS, DEVELOPER_KEY);
}

function netConnectionHandler(e:NetStatusEvent):void {
switch (e.info.code) {
case "NetConnection.Connect.Success":
trace(e.info.code);
myPeerID = netConnection.nearID;
initSendStream();
break;
}
}

// для отправки потока данных пиру
private function initSendStream() {
trace("initSendStream()");
sendStream = new NetStream(netConnection, NetStream.DIRECT_CONNECTIONS);
sendStream.addEventListener(NetStatusEvent.NET_STATUS, netStreamHandler);
sendStream.publish("media");
sendStream.attachAudio(Microphone.getMicrophone());
sendStream.attachCamera(Camera.getCamera());

var sendStreamClient:Object = new Object();
sendStreamClient.onPeerConnect = function(callers:NetStream):Boolean {
farPeerID = callers.farID;
trace("onPeerConnect "+farPeerID);
return true;
}
sendStream.client = sendStreamClient;
}

private function initRecvStream() {
trace("initRecvStream()");
trace("myPerrID = ", myPeerID);
recvStream = new NetStream(netConnection, myPeerID);
recvStream.addEventListener(NetStatusEvent.NET_STATUS, netStreamHandler);
recvStream.play("media");

video = new Video(320, 240);
video.attachNetStream(recvStream);
addChild(video);

recvStream.client = this;
}

function netStreamHandler(e:NetStatusEvent):void {
trace(e.info.code);
if (e.info.code=="NetStream.Publish.Start") {
initRecvStream();
}
}

}

}

Silicium
25.02.2012, 20:17
Вызов метода initRecvStream должен быть тут sendStreamClient.onPeerConnect, и передавать ему в качестве параметра callers.farID. И вот тут recvStream = new NetStream(netConnection, farID); он и должен быть в конструкторе

ashIndie
25.02.2012, 22:21
Вызов метода initRecvStream должен быть тут sendStreamClient.onPeerConnect, и передавать ему в качестве параметра callers.farID
не совсем понял...вот так?
var sendStreamClient:Object = new Object();
sendStreamClient.onPeerConnect = function(callers:NetStream):Boolean {
farPeerID = callers.farID;
trace("onPeerConnect "+farPeerID);
initRecvStream(farPeerID);
return true;
}
sendStream.client = sendStreamClient;

И вот тут recvStream = new NetStream(netConnection, farID); он и должен быть в конструкторе
как это написать в конструкторе, если нам еще не известен farID?

Silicium
25.02.2012, 22:47
initRecvStream(farPeerID);
Вот farPeerID - это оно и есть.
А так, как Вы делали:
recvStream = new NetStream(netConnection, myPeerID);
Это Вы к себе же и подключались)

ashIndie
25.02.2012, 23:05
немного разобрался.....
создал отдельно клиента и отдельно вещателя, после запуска в текстовое поле вставляю id и начинает вещать....плохо конечно но без задержек....
теперь вопрос....как сделать чтобы они автоматически обменивались ими и друг у другу подключались?

Добавлено спустя время:
Я могу узнать кто подключился ко мне и вещать данные с его камеры....но изначально как сделать чтобы они знали как друг к другу подключиться?....если peerID присваивается только во время подключения?
Silicium, Кстати спасибо большое, ты мне очень помог!!!

Silicium
25.02.2012, 23:17
http://melnaron.net/development/peer-to-peer-chat-in-flash

Вы это внимательно прочли? Сорц смотрели?

ashIndie
25.02.2012, 23:20
да но там php, хотелось бы обойтись без него

MikroAcse
26.02.2012, 00:27
Там php - только регистрация...
Можно и без нее обойтись.

ashIndie
26.02.2012, 00:28
Каким образом?

Добавлено через 43 минуты
есть еще кто не спит?....
последний штрих надо сделать....
но сижу над ним уже тоже долго

Добавлено через 2 часа 20 минут
Теперь проблема в другом. Тестировал все это дело на одном компьюетере, запуская просто в двух окнах браузера. Флешка сама на моем веб-сервере лежала, не локальном....Но щас другие люди не могут к ней подключиться..с других машин...в чем может быть проблема?

ЗлОй ПрОграММер
26.02.2012, 20:20
чтобы не плодить тем отпишусь здесь, надеюсь автор не против всё же задачи одинаковые
мне нужно связать 2 флешки, делал всё по этой теме но нечего не вышло(флешка не видит когда к ней подключатся другая) пожалуйста подскажите в чём ошибка
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.MouseEvent;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.events.NetStatusEvent;
import flash.text.TextField;
import flash.text.TextFormat;

public class MainClass extends MovieClip
{
private const CirrusAddress: String = "rtmfp://p2p.rtmfp.net/";
private const DeveloperKey: String = "xxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxx";

private var netConnection: NetConnection = new NetConnection();
private var nearPeerID: String;
private var farPeerID: String;

private var sendStream: NetStream;
private var recvStream: NetStream;

private var notificationText: TextField = new TextField();

public function MainClass(): void
{
//----------------------------------------------------------------------
if (stage) Initialization()
else addEventListener(Event.ADDED_TO_STAGE, Initialization);
//----------------------------------------------------------------------
}

private function Initialization(e: Event = null): void
{
//----------------------------------------------------------------------
addNotificationText();
//----------------------------------------------------------------------
netConnection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
netConnection.connect(CirrusAddress, DeveloperKey);
//----------------------------------------------------------------------
addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
removeEventListener(Event.ADDED_TO_STAGE, Initialization);
//----------------------------------------------------------------------
}

private function mouseDown(e: MouseEvent): void
{
//----------------------------------------------------------------------
sendMessage("P2P");
//----------------------------------------------------------------------
}

/*
* В случае, если с Cirrus состоялось успешное соединение, у NetStatusEvent.NET_STATUS свойству info.code
* будет присвоена строка «NetConnection.Connect.Success».
*/
private function netStatusHandler(e: NetStatusEvent): void
{
//----------------------------------------------------------------------
trace(e.info.code);
if (e.info.code == "NetConnection.Connect.Success")
{
nearPeerID = netConnection.nearID;
farPeerID = netConnection.farID;
initSendStream();
}
if (e.info.code == "NetStream.Publish.Start")
{

}
//----------------------------------------------------------------------
}

private function initSendStream(): void
{
//----------------------------------------------------------------------
sendStream = new NetStream(netConnection, NetStream.DIRECT_CONNECTIONS);
sendStream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
sendStream.publish("media");

var sendStreamClient: Object = new Object();
sendStreamClient.onPeerConnect = function(farStream: NetStream): Boolean
{
initRecvStream(farStream.farID);
return true;
}
sendStream.client = sendStreamClient;
//----------------------------------------------------------------------
}

private function initRecvStream(peerID: String): void
{
//----------------------------------------------------------------------
recvStream = new NetStream(netConnection, peerID);
recvStream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
recvStream.play("media");
recvStream.client = this;
//----------------------------------------------------------------------
}

public function sendMessage(message: String): void
{
//----------------------------------------------------------------------
sendStream.send("recvMessage", message);
recvMessage(message);
//----------------------------------------------------------------------
}

public function recvMessage(message: String): void
{
//----------------------------------------------------------------------
notificationText.appendText(message);
//----------------------------------------------------------------------
}

private function addNotificationText(): void
{
//----------------------------------------------------------------------
var textFormat: TextFormat;
//----------------------------------------------------------------------
textFormat = new TextFormat("Courier New", 20, null, true);
textFormat.align = "center";
notificationText.x = 0;
notificationText.y = 0;
notificationText.width = 800;
notificationText.height = 700;
notificationText.defaultTextFormat = textFormat;
notificationText.wordWrap = true;
notificationText.selectable = false;
addChild(notificationText);
//----------------------------------------------------------------------
}

}

}

Silicium
26.02.2012, 21:24
А кто к кому подключается? Запускаешь две флэшки - и они обе ждут подключения. Кто-то из ник должен первым приконнектиться к другому, а для этого ты должен создать слушающий поток с руками заданным farID, равным nearID первой запущенной флэшки

ЗлОй ПрОграММер
26.02.2012, 21:44
а есть где нить в исходниках пример такого слушащего потока ? а то я уж голову сломал как это всё работает
Башка кипит уже, так что извиняйте если чушь несу, моя задача узнать nearID первой флешки и вбить его сюда ?
private function initRecvStream(peerID: String): void
{
//----------------------------------------------------------------------
recvStream = new NetStream(netConnection, peerID);
recvStream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
recvStream.play("media");
recvStream.client = this;
//----------------------------------------------------------------------
}

Silicium
26.02.2012, 23:42
именно

ЗлОй ПрОграММер
28.02.2012, 11:47
в общем сделал как вы сказали и всё получилось, я передавал координаты мышки из одной флешки в другую. Но вот вопрос если мышка хотя бы секунд 5 неактивна то возникает событие NetStream.Connect.Closed С чем это может быть связано ? если не ошибаюсь оно должно возникать когда одна из флешек фокус потеряет

Silicium
29.02.2012, 00:32
у меня была такая проблема, когда я написал полностью статический класс для p2p соединения (буквально недавно, можете посмотреть темы, только ответа я так и не получил, хотя это скорее потому, что вопрос был весьма расплывчатый). короче говоря, у меня была проблема в том, что один из клиентов просто отваливался по непонятной причине. Переписал класс под синглтон - не отваливается. В чем причина - до сих пор понять не могу. По сути я просто из статик методов сделал не статик - проблема ушла.
ЗЫ если надо, могу поделиться классом. На звание библиотеки он не претендует, но свою роль наглядно выполняет - полезен, скорее, для понимания принципов p2p, хотя с ними вы вроде разобрались.

ЗлОй ПрОграММер
29.02.2012, 08:05
да был бы признателен если б скинули ваш класс для изучения, с потерей соединения я разобрался(ну как сказать, локально до сих пор одна из флешек теряет соединение, а залил на сервер и всё вроде работает нормально) да и ещё вот проблемка вчера при тестировании появилась. Захожу в приложение я и ещё один товарищ, я не смог подключиться к его флешке через его nearID, а у него получилось, попросил ещё одного человека протестировать тогда вроде такой проблемы не возникло, у вас не было такого ?