Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Flash > Серверные технологии и Flash

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 22.03.2012, 11:22
TMonax вне форума Посмотреть профиль Отправить личное сообщение для TMonax Найти все сообщения от TMonax
  № 1  
Ответить с цитированием
TMonax
 
Аватар для TMonax

Регистрация: Mar 2012
Сообщений: 7
По умолчанию Организация Socket сервера для Flash

Приветствую!
Пишу Delphi сервер - Flash клиент.
Долго парился с файлом политик... В результате, при подключении флешки от так:
Код AS3:
...
public class Main extends MovieClip {
 
		var address: String = "127.0.0.1";
		var port: int = 5000;
		var socket = new Socket();
 
		public function Main() {
			toggle_visible_btn.addEventListener(MouseEvent.CLICK, onToggleVisible, false, 0, true);
			socket.addEventListener(Event.CLOSE, sockClose);
			socket.addEventListener(Event.CONNECT, sockConnect);
			socket.addEventListener(ProgressEvent.SOCKET_DATA, sockSended);
			socket.addEventListener(IOErrorEvent.IO_ERROR, sockIOError);
			socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, sockSecurityError);
		}
 
		//
		private function onToggleVisible(evt: MouseEvent):void {
			trace("connection pressed");
			//Security.loadPolicyFile(ht);
			socket.connect(address, port);
		}
 
		private function sockClose(evt: Event): void {
			trace("sock closed");
		}
 
		private function sockConnect(evt: Event): void {
			trace("sock connected");
		}
 
		private function sockSended(evt: ProgressEvent): void {
			trace("sock sended");
		}
 
		private function sockIOError(evt: IOErrorEvent): void {
			trace("sock IO error!");
		}
 
		private function sockSecurityError(evt: SecurityErrorEvent): void {
			trace("sock security error!");
		}
	}
...
На сервер сразу идёт строка:
Код:
'<policy-file-request/>' + #0(нулевой байт)
Я её принимаю, и в ответ посылаю следующую строку:
Код:
'<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*" to-ports="*" secure="false" />
</cross-domain-policy>' + #0;
При таком раскладе мне наконец-то удалось избежать всяких ошибок на стороне флешки по поводу недопустимости файла политик и всякого такого...
И после этого соединение у флешки сохраняется, выводится trace "sock connected". Вроде всё корошо, как бы общайся дальше данными.
Но, взглянем в лог сервера:
[02:49:15]: +++ Сервер запущен +++
[02:50:15]: from 127.0.0.1:51105: Соединение установлено!
[02:50:15]: from 127.0.0.1:51105: принят <policy-file-request/>
[02:50:15]: from 127.0.0.1:51105: Клиент закрыл соединение(закрыт сокет)
[02:50:15]: from 127.0.0.1:51105: Нить остановлена
[02:50:15]: from 127.0.0.1:51107: Соединение установлено!
...
Т.е. флэш клиент, после того как получил файл политик, разрывает соединение и устанавливает его заново!
А чуть позже я увидел пост о том, что можно держать сервер, который раздаёт только файлы политик и больше ничего, вообще отдельно от основного сервера, но как тогда посылать запрос файла политик, ведь тут я просто конектюсь к основному серверу, а флешка уже сама запрашивает у этого адреса файл политик.
нужно воспользоваться Security.loadPolicyFile() ? тогда что правильно писать в скобках, т.е. как правильно писать адрес сервера для такого сокет сервера как у меня? а то примеры котоыре я видел в основном для веб севреров или ещё чего-то...

Теперь идём дальше, допустим что я наладил первое подключение по вышежелаемой схеме.
Теперь, какими данными общаться с основным сервером?
У меня такое мнение слаживается, что общаться прийдётся строками, которые заканчиваются на нулевой байт... Т.е. я опять же видел упоминание этого на каком-то форуме, что: "флеш отправляя строку серверу, всегда в конец добавляет нулевой байт" - типа этот байт служит нам флагом для разделения пакетов на сервере. и далее: "так же и серверу необходимо отсылать строки, добавляя в конец нулевой байт" - типа флешка так тоже автоматом распознает отдельные пакеты и выдаст их в функцию обработки события ProgressEvent.SOCKET_DATA.

Но во всех сетевых приложениях, которые я разрабатывал до этого, я общался следующей структурой:
Код:
// определённая структура заголовка пакета
TPackHeader = record
  PackName      : TPackNameType;  // числовое значение - идентификатор типа пакета
  PackBodySize  : TPackBodyType;  // 4 byte(int32) размер массива байт, который идёт сразу после заголовка пакета
end;
Т.е. когда подключается клиент, то анализатор буфера сокета заранее знает, что первым будет заголовок, потом в заговке он читает размер тела пакета и после приёма байт тела опять переключается на чтение заголовка(следующего пакета) и т.д.
А с флешем получается только строки можно передавать чтоли? Конечно я могу адаптировать посылку и приём для строк, в этом случае разделителями пакетов будут нулевые байты, но мне бы всётаки хотелось формировать байтовые пакеты и посылать их как массивы байт, какими я и пользовался...

Ещё интересует отличие типа socket и XMLSocket во флеше... в чём разница, когда тот или другой применяется или может применяться?
я, например, использую:
Код AS3:
var socket = new Socket();
А т.к. конечная цель - это рпиложение для вконя(вконтакте), то заодно спрошу, какую строку политики надо использовать для него?
Вот такую?:
Код:
<?xml version="1.0"?>
<cross-domain-policy>
<site-control permitted-cross-domain-policies="master-only"/>
<allow-http-request-headers-from domain="vk.com" headers="*"/>
<allow-http-request-headers-from domain="*.vk.com" headers="*"/>
<allow-http-request-headers-from domain="vkontakte.ru" headers="*"/>
<allow-http-request-headers-from domain="*.vkontakte.ru" headers="*"/>
<allow-access-from domain="vk.com" to-ports="80" />
<allow-access-from domain="*.vk.com" to-ports="80" />
<allow-access-from domain="vkontakte.ru" to-ports="80" />
<allow-access-from domain="*.vkontakte.ru" to-ports="80" />
</cross-domain-policy>
Вот вообщем хочется подробно, последовательно обсудить данную архитектуру, а то как-то уже запарило лазить по всему инету и анализировать всякие клочки информации.
Ах да, подскажите ещё, какую книгу взять, где бы по сокетам добротно было расписано?

Очень надеюсь на помощь

Старый 22.03.2012, 12:33
bav вне форума Посмотреть профиль Отправить личное сообщение для bav Найти все сообщения от bav
  № 2  
Ответить с цитированием
bav
 
Аватар для bav

Регистрация: Oct 2010
Сообщений: 1,049
Отправить сообщение для bav с помощью ICQ
Цитата:
Но, взглянем в лог сервера:
[02:49:15]: +++ Сервер запущен +++
[02:50:15]: from 127.0.0.1:51105: Соединение установлено!
[02:50:15]: from 127.0.0.1:51105: принят <policy-file-request/>
[02:50:15]: from 127.0.0.1:51105: Клиент закрыл соединение(закрыт сокет)
[02:50:15]: from 127.0.0.1:51105: Нить остановлена
[02:50:15]: from 127.0.0.1:51107: Соединение установлено!
Это нормально. Если вы отдаете файл политики по тому же порту, на котором сидит и основной сервер, то flash player сам, автоматически, отключается после получения файла политик. При этом в коде клиента это выглядит просто как подключение к основному серверу.
Цитата:
А чуть позже я увидел пост о том, что можно держать сервер, который раздаёт только файлы политик и больше ничего, вообще отдельно от основного сервера, но как тогда посылать запрос файла политик, ведь тут я просто конектюсь к основному серверу, а флешка уже сама запрашивает у этого адреса файл политик.
Все верно. Отдельный небольшой сервер, который сидит на 843 порту и только то и делает, что раздает файлы политик клиентам после того как получит от них <policy-file-request/>. При этом этот сервер должен сам закрывать соединение с клиентом как только отдаст файл политик. При этом опять таки в коде клиента это выглядит как простое подключение к основному серверу. Плеер сам вначале попробует постучаться на 843 порт за файлом политик.
Цитата:
Т.е. когда подключается клиент, то анализатор буфера сокета заранее знает, что первым будет заголовок, потом в заговке он читает размер тела пакета и после приёма байт тела опять переключается на чтение заголовка(следующего пакета) и т.д.
Посмотрите методы класса Socket, с их помощью можно отправлять не только строки.
P.S. По ссылке выше можно найти и "Подключение к сокетам".


Последний раз редактировалось bav; 22.03.2012 в 12:36.
Старый 22.03.2012, 16:29
TMonax вне форума Посмотреть профиль Отправить личное сообщение для TMonax Найти все сообщения от TMonax
  № 3  
Ответить с цитированием
TMonax
 
Аватар для TMonax

Регистрация: Mar 2012
Сообщений: 7
bav, спасибо добрый человек! понятно и спокойно прояснил некоторые детали.
Насчёт того, что отключение после съедания файла политик нормально - это я конечно понял, от этого и хотел выяснить как она поступает вообще) её логику так сказать.
Если честно, то мне уже чудно то, что во флешке разработчику никак не показывается это своевольное переподключение)

Хочу уточнить некоторые моменты,
т.е. я могу располагать отдельный сервер для файлов политик на этом же ip(главного сервера), только на 843 порт,
затем во флешке конект врубать сразу на порт главного сервака
и при этом флешка сначало разберёться с файлом политик на 843-ем порту,
а потом законектится без всяких запросов уже на порт главного сервака?
Если так, то это чудно)

Документация эта у меня уже открыта, читал, но для хорошего понимания и закрепления решил пообщаться с людьми на форуме)

Ну и актуальный вопрос остаётся - это файл политик для ВКоня, как собствено его правильно писать?
Правильна ли та версия, которую я написал?

Старый 22.03.2012, 18:33
bav вне форума Посмотреть профиль Отправить личное сообщение для bav Найти все сообщения от bav
  № 4  
Ответить с цитированием
bav
 
Аватар для bav

Регистрация: Oct 2010
Сообщений: 1,049
Отправить сообщение для bav с помощью ICQ
Цитата:
Хочу уточнить некоторые моменты...
Да, все так как вы и написали. Про ВКонтакт, к сожалению, ничего на знаю.

Старый 11.04.2012, 20:17
TMonax вне форума Посмотреть профиль Отправить личное сообщение для TMonax Найти все сообщения от TMonax
  № 5  
Ответить с цитированием
TMonax
 
Аватар для TMonax

Регистрация: Mar 2012
Сообщений: 7
Появилась какая-то непонятная неприятность...
Соединение с серваком устанавливается нормально, срабатывает событие cliSock.addEventListener(Event.CONNECT, onSocketConnect);
в его обработке следующее:
Код AS3:
private function onSocketConnect(evt: Event): void {
	trace("Соединение по назначенному адресу установлено");
	// посылаем пакет-запрос на пингование			
	cliSock.writeInt(2);cliSock.writeInt(1);cliSock.writeByte(0);	
}
Данный пакет приходит на сервак, всё нормально, сервак сразу же посылает ответ, флешка фиксирует ответ.
Далее я на кнопку сделал такую же посылку, т.е. тот же пакет.
Вот обработка:
Код AS3:
private function onBtnConnectPress(evt: MouseEvent):void {		
	trace("запрашиваем пинг");
	cliSock.writeInt(2);cliSock.writeInt(1);cliSock.writeByte(0);				
}
Нажимаю на кнопку и ноль эмоций.... Вообще ни одного байта на сервак не приходит.
При этом если я в обработке подключения сделаю так:
Код AS3:
private function onSocketConnect(evt: Event): void {
	trace("Соединение по назначенному адресу установлено");
	// посылаем пакет-запрос на пингование			
	cliSock.writeInt(2);cliSock.writeInt(1);cliSock.writeByte(0);
        cliSock.writeInt(2);сliSock.writeInt(1);cliSock.writeByte(0);	
        cliSock.writeInt(2);cliSock.writeInt(1);cliSock.writeByte(0);	
}
То все 3 запроса пинга благополучно приходят на сервак и все 3 ответа приходят на флешку...

Старый 11.04.2012, 21:29
-De- вне форума Посмотреть профиль Отправить личное сообщение для -De- Найти все сообщения от -De-
  № 6  
Ответить с цитированием
-De-
 
Аватар для -De-

блогер
Регистрация: Oct 2005
Адрес: Днепродзержинск - город Брежнева и других логопедов
Сообщений: 1,421
Записей в блоге: 4
Отправить сообщение для -De- с помощью ICQ Отправить сообщение для -De- с помощью Skype™
А если cliSock.flush(); ? И что сниффер говорит?
Ну и на уровне сокетов вообще-то нет пакетов, это поток.
__________________
Бобры отвечают на вопросы не потому, что знают на них ответы; они отвечают потому, что их спрашивают.

Старый 11.04.2012, 23:35
TMonax вне форума Посмотреть профиль Отправить личное сообщение для TMonax Найти все сообщения от TMonax
  № 7  
Ответить с цитированием
TMonax
 
Аватар для TMonax

Регистрация: Mar 2012
Сообщений: 7
Цитата:
Сообщение от -De- Посмотреть сообщение
А если cliSock.flush(); ? И что сниффер говорит?
Свершилось, дело было в отсутствии flush(), а точнее я его пробовал но писал его перед write методом - думал надо сначало очистить буфер, прежде чем слать что-то новое и решил что толку от него нет...
На самом деле странно, т.к. в руководстве не написано что этот метод есть команда "отправить!"...

PS: опять же я поспешил в чтении руководства и не обратил внимания на понятное пояснение:
"Очищает любые накопленные данные в выходном буфере сокета.
В одних операционных системах метод flush() автоматически вызывается между кадрами выполнения, а в других, таких как Windows, данные никогда не отправляются, пока в коде не будет вызван метод flush(). Чтобы обеспечить надежное поведение приложения во всех операционных системах, рекомендуется вызывать метод flush() после записи каждого сообщения (или связанной группы данных) в сокет."

А я прочитал только первое предложение... поспешил - насмешил вообщем.
Цитата:
Сообщение от -De- Посмотреть сообщение
Ну и на уровне сокетов вообще-то нет пакетов, это поток.
Ну конечно же мы тут все не глупые и должны были понять, что пакетом, тем более своим, я называю условный набор байт)


Последний раз редактировалось TMonax; 11.04.2012 в 23:42.
Старый 16.04.2012, 00:43
KVinS вне форума Посмотреть профиль Отправить личное сообщение для KVinS Найти все сообщения от KVinS
  № 8  
Ответить с цитированием
KVinS

Регистрация: Nov 2009
Сообщений: 108
Что такое?
Пишу во флеше
Код AS3:
Security.loadPolicyFile("xmlsocket://"+serverName.text+":843");
telnetClient = new Telnet(serverName.text, int(portNumber.text), output);
Запускаю сервер политик. И всё.
Со стороны флеша ошибка.
Со стороны сервера тишина.

Код:
package Server;

/**
 *
 * @author 1
 */
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Class PolicyServer
 * Starts a PolicyServer on the specified port.
 * Can be started as main class, passing the port number as the first command line argument
 * @author Thomas Meyer, Less Rain (thomas@lessrain.com)
 *
 */
public class PolicyServer extends Thread
{
 /**
  * Если аргумент не передается на сервер будет слушать этот порт для соединения
  */
 public static final int DEFAULT_PORT = 843;
 public static final String[] DEFAULT_POLICY = new String[] { "*" };


 /**
  * Последовательность символов, прислал Flash Player просить _policy файл
  */
 public static final String POLICY_REQUEST = "<policy-file-request/>";

 public static final boolean DEBUG = true;

 /**
  * @param args Использование первого аргумента командной строки для установки порт сервера будет слушать для соединений
  */
 public static void main(String[] args)
 {
  int port = DEFAULT_PORT;
  try
  {
   if (args.length>0) port = Integer.parseInt(args[0]);
  }
  catch (NumberFormatException e) {}

  // Начало PolicyServer
  (new PolicyServer( port , new String[] { "*:500" })).start();
 }


 /*
  * переменных olicyServer класса
  */
 private int _port;
 private boolean _listening;
 private ServerSocket _socketServer;
 private String _policy;


 /**
  * PolicyServer constructor
  * @param port_ Устанавливает порт, который прослушивает PolicyServer
  */
 public PolicyServer( int port_, String[] allowedHosts_ )
 {
  _port = port_;
  _listening=true;
  if (allowedHosts_==null) allowedHosts_ = DEFAULT_POLICY;
  _policy = buildPolicy(allowedHosts_);
 }

 private String buildPolicy( String[] allowedHosts_ )
 {
  StringBuffer policyBuffer = new StringBuffer();

  policyBuffer.append("<?xml version=\"1.0\"?><cross-domain-policy>");
  for (int i = 0; i < allowedHosts_.length; i++) {
   String[] hostInfo = allowedHosts_[i].split(":");
   String hostname = hostInfo[0];
   String ports;
   if (hostInfo.length>1) ports = hostInfo[1];
   else ports = "*";

   policyBuffer.append("<allow-access-from domain=\""+hostname+"\" to-ports=\""+ports+"\" />");
  }
  policyBuffer.append("</cross-domain-policy>");

  return policyBuffer.toString();
 }

 /**
  * Поток запуска метода, принимает входящие соединения и создает SocketConnection объектов для обработки запросов
  */
 public void run()
 {
  try
  {
   _listening=true;

   // Начало прослушивает соединения
   _socketServer = new ServerSocket(_port,50);
   if (DEBUG) System.out.println("PolicyServer listening on port "+_port);

   while(_listening)
   {
    // Дождитесь соединения и принять его
    Socket socket = _socketServer.accept();

    try
    {
     if (DEBUG) System.out.println("PolicyServer got a connection on port "+_port);
     // Начать новую тему связи
     (new SocketConnection(socket)).start();
    }
    catch (Exception e)
    {
     if (DEBUG) System.out.println("Exception: "+e.getMessage());
    }
    try
    {
     // Подождите секунду, пока новое соединение будет принято, чтобы избежать затопления
     sleep(1000);
    }
    catch (InterruptedException e) {}
   }
  }
  catch(IOException e)
  {
   if (DEBUG) System.out.println("IO Exception: "+e.getMessage());
  }
 }

 /**
  * Местные SocketConnection класса
  * Для каждого принятого соединения один SocketConnection создается.
  * Он ждет _policy файл запроса, возвращает _policy файл и закрывает соединение сразу
  * @author Thomas Meyer, Less Rain (thomas@lessrain.com)
  *
  */
 class SocketConnection extends Thread
 {
  private Socket _socket;
  private BufferedReader _socketIn;
  private PrintWriter _socketOut;

  /**
   * Конструктор принимает объект Socket для связи
   * @param socket_ Socket соединения с клиентом созданные PolicyServer основной поток
   */
  public SocketConnection(Socket socket_)
  {
   _socket = socket_;
  }

  /**
   * Тема запуска метода ждет _policy запроса, возвращает poilcy файл и закрывает соединение
   */
  public void run()
  {
   try
   {
    // инициализации сокета и читателей / писателей
    _socket.setSoTimeout(10000);
    _socketIn = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
    _socketOut =new PrintWriter(_socket.getOutputStream(), true);
   }
   catch (IOException e)
   {
    if (DEBUG) System.out.println("IO Exception "+e.getMessage());
    return;
   }

   readPolicyRequest();
  }

  /**
   * Подождите, и читать _policy запроса, отправленного Flash Player
   * Вернуться _policy файл и закрыть соединение гнезда
   */
  private void readPolicyRequest()
  {
   try
   {
    // Читайте запроса и сравнить его с запроса строку, определенную в постоянные.
    // Если в надлежащем запрос _policy был отправлен выписать _policy файл
    if (POLICY_REQUEST.equals(read()))
                {
                    write(_policy);
                }
   }
   catch (Exception e)
   {
    if (DEBUG) System.out.println("Exception "+e.getMessage());
   }
   close();
  }

  /**
   * Читайте до нуля характер передается или максимум 100 символов
   * @return The character sequence read
   * @throws IOException
   * @throws EOFException
   * @throws InterruptedIOException
   */
  private String read() throws IOException, EOFException, InterruptedIOException
  {
   StringBuffer buffer = new StringBuffer();
   int codePoint;
   boolean zeroByteRead=false;

   if (DEBUG)
                {
                    System.out.println("Reading...");

                }
   do
   {
    codePoint=_socketIn.read();
    if (codePoint==0) zeroByteRead=true;
    else buffer.appendCodePoint( codePoint );
   }
   while (!zeroByteRead && buffer.length()<100);
   if (DEBUG) System.out.println("Read: "+buffer.toString());

   return buffer.toString();
  }

  /**
   *Записывает строку в клиента
   * @param msg Текст для отправки клиенту (_policy файл)
   */
  public void write(String msg)
  {
   _socketOut.println(msg+"\u0000");
            _socketOut.flush();
   if (DEBUG) {
                System.out.println("Wrote: "+msg);

            }
  }

  /**
   * Закрытие соединения Socket все установить нулевые. Подготовлено для сбора мусора
   */
  public void close()
  {
   try
   {
    if (_socket!=null) _socket.close();
    if (_socketOut!=null) _socketOut.close();
    if (_socketIn!=null) _socketIn.close();
                System.out.println("Port close.");
   }
   catch (IOException e) {}

   _socketIn=null;
   _socketOut=null;
   _socket=null;
  }

 }

}

Создать новую тему Ответ Часовой пояс GMT +4, время: 19:28.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 19:28.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.