Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование игр для мобильных телефонов > MidletPascal > Библиотеки

Ответ
 
Опции темы
Старый 20.08.2009, 19:09   #1
ViNT
Модератор
 
Регистрация: 03.04.2007
Сообщений: 2,252
Написано 597 полезных сообщений
(для 817 пользователей)
Lib_binsock: прием/отправка бинарных данных через сокет

Lib_binsock - библиотека для работы с сокетами в трех режимах:
-побайтно(прием/передача)
-прием/передача массивов бинарных данных
-InputStream(Resource)

Обновление. В версии 1.1 добавлена функция flush для немедленной отправки данных

Библиотека содержит следующие функции:

procedure debug_register(idx:integer);
Устанавливает библиотеке идентификатор, который будет передаваться
в обработчик ошибок (о нем ниже) в случае возникновения исключительной ситуации(Exception).

procedure enable_debug(flag:integer);
Включает/отключает режим отладки.
flag = 1 - включить
flag = -1 - выключить
По умолчанию отладка отключена.

Если отладка включена, то в случае возникновения ошибки
вызывается процедура-обработчик, определенная в главной программе, например:

//sender - числовой идентификатор библиотеки, присваиваемый с помощью debug_register
//exception - системное сообщение об ошибке
//errstr - дополнительное сообщение (указанное при компиляции библиотеки)
//code - код ошибки (указанный при компиляции библиотеки)
procedure onerror(sender:Integer;exception:string;errstr:string;code:integer);
//Имя процедуры, порядок и тип параметров должны быть соблюдены !
begin
 cmOK
:=CreateCommand('OK',CM_OK,1);
 
ShowAlert('Error #'+IntegerToString(code),'Exception: '+exception+chr(10)+chr(13)+'ErrorString: '+errstrLoadImage('/icon.png'),ALERT_ERROR);
 
delay(20000);
 
ShowForm;
end
Параметр code может иметь следующие значения:

int ERR_OPENERROR = 0; - ошибка открытия сокета
int ERR_CLOSEERROR = 1; - ошибка закрытия сокета
int ERR_AVAILERROR = 2; - ошибка при определении размера буфера
int ERR_READERROR = 3; - ошибка получения данных
int ERR_WRITEERROR = 4; - ошибка отправки данных


Внимание!
В случае, если отладка включена, обработчик должен присутствовать обязательно,
иначе возможен сбой в работе мидлета; если отладка отключена, обработчик объявлять не обязательно.


function open(url:string):integer;
Открывает соединение с адресом url.
Формат url стандартный:
socket://url:port

Возвращает 1 в случае успеха, иначе возвращает -1 и передает в обработчик сообщение об ошибке ERR_OPENERROR.

procedure close;
Закрывает соединение.

В случае неудачи передает в обработчик сообщение об ошибке ERR_CLOSEERROR.

function available:integer;
Возвращает размер доступных для приема данных.

В случае неудачи возвращает -1 и передает в обработчик сообщение об ошибке ERR_AVAILERROR.

function read_byte:integer;
Возвращает следующий байт данных из буфера приема, в случае неудачи возвращает -1 и передает в обработчик сообщение об ошибке ERR_READERROR.

function write_byte(data:integer):integer;
Записывает в буфер передачи байт data.

Возвращает 1 в случае успеха, иначе возвращает -1 и передает ошибку ERR_WRITEERROR.

function get_in_stream:resource;
Возвращает поток resource для подключения.

function write_bin(data:string):integer;
Записывает массив байт data в поток передачи.

Возвращает 1 в случае успеха, иначе возвращает -1 и передает ошибку ERR_WRITEERROR.

function read_bin(len:integer):string;
Возвращает массив байт из входящего потока.

В случае неудачи возвращает null и передает в обработчик сообщение ERR_READERROR.

function rx_count:integer;
Возвращает количество принятых данных.

function tx_count:integer;
Возвращает размер принятых данных.

function flush:integer; c версии 1.1

Инициирует немедленную отправку данных на сервер

Возвращает 1 в случае успеха, иначе возвращает -1 и передает в обработчик сообщение об ошибке
ERR_FLUSHERROR.

Внимание!
---------

Библиотека требует доступа к сети

Проверено на Motorola L9.

Отправку данных проверить не смог, но должно работать.


P.S. Предлагаю всем разработчикам в своих новых библиотеках (еще лучше и старые переделать) использовать такой же принцип обработки ошибок. Чуть позже опишу принцип подробнее. Основная идея состоит в том, чтобы использовать общий обработчик для обработки ошибок от всех библиотек.
Вложения
Тип файла: zip Lib_binsock1.1.zip (12.7 Кб, 1318 просмотров)

Последний раз редактировалось ViNT, 10.04.2010 в 21:50.
(Offline)
 
Ответить с цитированием
Эти 5 пользователя(ей) сказали Спасибо ViNT за это полезное сообщение:
impersonalis (25.08.2009), johnk (20.08.2009), odd (03.12.2009), Pyth_ON (26.02.2010), Skythrone (21.08.2009)
Старый 24.08.2009, 22:44   #2
Skythrone
ПроЭктировщик
 
Регистрация: 02.07.2008
Сообщений: 105
Написано 7 полезных сообщений
(для 14 пользователей)
Ответ: Lib_binsock: прием/отправка бинарных данных через сокет

ViNT, спасибо за либу! Весьма полезна.

Но в процессе тестирования на реальных телефонах обнаружилось следующее:

1. Даже если не делать обработчик ошибок, всё равно на некоторых самсунгах может не запускаться. И через обфускатор proguard не проходит. Если создать хотя бы пустую процедуру onerror, то всё ОК. Надеюсь, эта информация пригодится тем, кто будет использовать данную либу.

2. Приём данных я делаю примерно так:

count := binsock.available;
content := '';
while (
count>0) do
begin
 content 
:= content binsock.read_bin(count);
 
count := binsock.available;
end
т.е. всё скачиваю в текстовую переменную.
Я так понял, что при загрузке сначала заполняется некий буфер, а потом уже из него можно скачивать в бинарный массив.
Подобный цикл while..end понадобился, поскольку размер буфера значительно меньше размера реально скачиваемого с сервера контента.
На эмуляторе kEmulator переменная count, отображающая binsock.available, принимает максимальное значение 8192. То есть когда я скачиваю с сервера 20 кб данных, цикл проходит 3 раза.
Но бинарная картинка, скачанная таким образом, нормально собирается и отображается на эмуляторе.

На мобильниках всё не так радужно. Например, на Samsung E-200 размер буфера всего 512 байт. Текстовый контент в приведённом мной выше цикле скачивается и собирается нормально, а вот картинка - нет, приходит битая.

Может, сможешь что-нибудь посоветовать?
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
ViNT (25.08.2009)
Старый 25.08.2009, 03:03   #3
ViNT
Модератор
 
Регистрация: 03.04.2007
Сообщений: 2,252
Написано 597 полезных сообщений
(для 817 пользователей)
Ответ: Lib_binsock: прием/отправка бинарных данных через сокет

Спасибо за подробный баг-репорт, буду разбираться.
На счет некорректного приема картинки - надо бы сохранить данные в файл и сравнить с оригиналом, может станет понятно, в чем дело.
По поводу размера буфера - посмотрю, что по этому поводу написано в доках.
(Offline)
 
Ответить с цитированием
Старый 03.12.2009, 11:54   #4
rangel
AnyKey`щик
 
Аватар для rangel
 
Регистрация: 02.12.2009
Сообщений: 18
Написано 0 полезных сообщений
(для 0 пользователей)
Ответ: Lib_binsock: прием/отправка бинарных данных через сокет

а можно примерчит отправки скажем текста
на определённый айпишник, через udp
(Offline)
 
Ответить с цитированием
Старый 23.02.2010, 16:36   #5
Topaz1977
AnyKey`щик
 
Регистрация: 25.06.2009
Сообщений: 2
Написано одно полезное сообщение
Ответ: Lib_binsock: прием/отправка бинарных данных через сокет

Работает нормально, но при проверке на современных телефонах (SE C510 и некоторые Nokia) -не отправляет данные сразу. В процессе разбора полетов выяснилось-телефоны упорно буферизируют данные на отправку. Вылечилось добавлением
public static int write_byte(int data){
tx++;
try{
os.write(data);
os.flush(); <-----Вот этого
return 1;
}catch(Exception e){
err(e, ERR_WRITEERROR, "Error writing byte to stream");
return -1;
}
}

public static int write_bin(String data){
byte d[] = data.getBytes();
tx = tx+d.length;
try{
os.write(d);
os.flush(); <-----и этого
}catch(Exception e){
err(e, ERR_WRITEERROR, "Error writing binary to stream");
return -1;}
return 1;
}
(Offline)
 
Ответить с цитированием
Старый 23.02.2010, 22:44   #6
odd
Мастер
 
Аватар для odd
 
Регистрация: 06.09.2007
Адрес: Донецк, ДНР
Сообщений: 1,023
Написано 298 полезных сообщений
(для 713 пользователей)
Ответ: Lib_binsock: прием/отправка бинарных данных через сокет

Да. FLUSH нужно делать обязательно.
На любых телефонах.
(Offline)
 
Ответить с цитированием
Старый 10.04.2010, 20:59   #7
peps
AnyKey`щик
 
Регистрация: 10.04.2010
Сообщений: 2
Написано 0 полезных сообщений
(для 0 пользователей)
Ответ: Lib_binsock: прием/отправка бинарных данных через сокет

Сообщение от Topaz1977 Посмотреть сообщение
Работает нормально, но при проверке на современных телефонах (SE C510 и некоторые Nokia) -не отправляет данные сразу. В процессе разбора полетов выяснилось-телефоны упорно буферизируют данные на отправку. Вылечилось добавлением
public static int write_byte(int data){
tx++;
try{
os.write(data);
os.flush(); <-----Вот этого
return 1;
}catch(Exception e){
err(e, ERR_WRITEERROR, "Error writing byte to stream");
return -1;
}
}

public static int write_bin(String data){
byte d[] = data.getBytes();
tx = tx+d.length;
try{
os.write(d);
os.flush(); <-----и этого
}catch(Exception e){
err(e, ERR_WRITEERROR, "Error writing binary to stream");
return -1;}
return 1;
}
Выложите пожалуйста исправленную версию кто нибудь.
(Offline)
 
Ответить с цитированием
Старый 10.04.2010, 21:51   #8
ViNT
Модератор
 
Регистрация: 03.04.2007
Сообщений: 2,252
Написано 597 полезных сообщений
(для 817 пользователей)
Ответ: Lib_binsock: прием/отправка бинарных данных через сокет

Добавил функцию flush
(Offline)
 
Ответить с цитированием
Старый 10.04.2010, 21:54   #9
peps
AnyKey`щик
 
Регистрация: 10.04.2010
Сообщений: 2
Написано 0 полезных сообщений
(для 0 пользователей)
Радость Ответ: Lib_binsock: прием/отправка бинарных данных через сокет

Сообщение от ViNT Посмотреть сообщение
Добавил функцию flush
Спасибо! Очень оперативно!
(Offline)
 
Ответить с цитированием
Старый 27.04.2012, 18:47   #10
AssA
AnyKey`щик
 
Аватар для AssA
 
Регистрация: 31.07.2011
Сообщений: 10
Написано 0 полезных сообщений
(для 0 пользователей)
Ответ: Lib_binsock: прием/отправка бинарных данных через сокет

добрый день
спасибо за либу, пользую, работает отлично.

есть вопрос:
присылаю с сервера (delphi 2007, ServerSocket) текст с русскими буквами:

тел. НОКИА:
текст в ANSI: read_bin возвращает в строке символы ANSI, читаю посимвольно, преобразую в UTF8 - вопросов нет.
текст в UTF8: русские буквы приходят по 2 байта (как и положено)

тел. LG:
текст в ANSI: read_bin возвращает только часть строки ДО первой русской буквы
текст в UTF8: принимает на ура, даже преобразовывать ничего не надо.

ВОПРОС
каким образом можно оптимально заставить оба тел работать? сам я решение предполагаю, и не одно, но они мне не нравяться. LG при получении бинарного потока корректно распознает в нем русские буквы при копировании в строку, нокиа же, просто раскладывает - в каждый символ один байт.

буду признателен всем ответившим.


привожу свою функцию для преобразования данных из сокета в utf8 с русскими символами, может пригодиться кому нибудь. (функция фильтрует управляющие символы. этой же функцией можно читать русский текст из RecordStore)

function scr_frBIN(s: string): string; // (from BIN, ANSI to UTF)
var
  i,l,co: integer;
  ch: char;
  re: string;
begin
  re:= '';
  l:= length(s)-1;
  for i:=0 to l do begin
    ch:= getChar(s,i);
    co:= ord(ch);
    if co>31 then 
      if co<127 then re:= re+ch
      else if co>191 then re:= re+chr(co+848)
        else if co=168 then re:= re+chr(1025)
          else if co=184 then re:= re+chr(1105);
  end;
  scr_frBIN:= re;
  re:= '';
end;
(Offline)
 
Ответить с цитированием
Старый 28.04.2012, 00:26   #11
ViNT
Модератор
 
Регистрация: 03.04.2007
Сообщений: 2,252
Написано 597 полезных сообщений
(для 817 пользователей)
Ответ: Lib_binsock: прием/отправка бинарных данных через сокет

Просто режет строку, в обработчик ошибок ничего не сваливается, мидлет не зависает? Вообще, если режет символы даже в бинарном режиме, то вряд ли что-то модно сделать. Хотя, надо посмотреть, может и есть решение.
(Offline)
 
Ответить с цитированием
Старый 02.05.2012, 12:33   #12
AssA
AnyKey`щик
 
Аватар для AssA
 
Регистрация: 31.07.2011
Сообщений: 10
Написано 0 полезных сообщений
(для 0 пользователей)
Ответ: Lib_binsock: прием/отправка бинарных данных через сокет

провел тест на LG ( gw300 ):

binsock.debug_register(0);
binsock.enable_debug(-1);

ansi:
отправил: 123фф123
на тел:123? ( len = 4 )
utf-8:
отправил: 123фф123
на тел: 123фф123 ( len = 8 )

binsock.debug_register(1);
binsock.enable_debug(1);

результат тот же, ошибок нет. после получения русских "вопросиков" мидлет продолжает работать. вот исходник теста: (в первом тесте процедуры onerror не было)

program testscr;
uses
  binsock;

var
  IsConn, l : integer;
  rx: string;
  b: integer;
  res: resource;

  cmOK: command;

procedure onerror(sender:Integer;exception:string;errstr:string;code:integer);
begin
  cmOK:= CreateCommand('OK',CM_OK,1);
  ShowAlert('Error #'+IntegerToString(code),'Exception: '+exception+chr(10)+chr(13)+'ErrorString: '+errstr, LoadImage('/icon.png'),ALERT_ERROR);
  repeat delay(200);
  until getClickedCommand = cmOK;
end;

procedure clr;
begin
  showCanvas;
  setFont(FONT_FACE_SYSTEM, 0, FONT_SIZE_SMALL);
  SetColor(0,0,0);
  fillRect(0,0, getwidth, getheight);
  SetColor(0,255,0);
end;

procedure txt(s: string; y: integer;);
begin
  drawtext(s, 5, y);
  repaint;
end;

begin
  // scr
  clr;

  // сокеты
  binsock.debug_register(1);
  binsock.enable_debug(1);

  // connect
  IsConn:= binsock.open( 'socket://xxxx:2286' );
  delay(3000);

  if IsConn=1
    then txt('connected!', 10)
    else halt;

  // loop
  repeat
    rx:= '';

    // read sock
    l:= binsock.available;
    while l>0 do begin
      rx:= rx + binsock.read_bin(l);
      l:= binsock.available;
    end;

    // show
    l:= length(rx);
    if l>0 then begin
      clr;
      txt( integertostring(GetCurrentTime), 10 );
      txt( 'rx len='+IntegerToString(l), 30  );
      txt( rx, 50 );
    end;

    delay(100);
  until GetKeyPressed <> KE_NONE;

end.
отправка с сервера в сокет выглядела так (delphi 2007):
procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
  us: UTF8String;
begin
  us:= AnsiToUtf8( Edit1.Text );
  for i:= 0 to ServerSocket1.Socket.ActiveConnections-1 do
    if CheckBox1.Checked then // птичка "отправлять в utf-8"
      ServerSocket1.Socket.Connections[i].SendText( us )
    else
      ServerSocket1.Socket.Connections[i].SendText( Edit1.Text );

end;
продолжил тесты:

функция binsock.read_byte возвращает именно байты. если пришел ansi - получим именно их коды, utf - по два байта на каждую русскую букву.

то есть засада в функции binsock.read_bin() - мне кажется, когда присваивается результат, NOKIA и LG воспринимают это по-разному: нокиа строго раскладывает побайтно, lg в этом потоке бинарных данных рассматривает utf8 символы и преобразует находу. можно ли и NOKIA заставить "распознавать" строку UTF-8 ?

Последний раз редактировалось AssA, 02.05.2012 в 13:43.
(Offline)
 
Ответить с цитированием
Старый 06.05.2012, 00:17   #13
ViNT
Модератор
 
Регистрация: 03.04.2007
Сообщений: 2,252
Написано 597 полезных сообщений
(для 817 пользователей)
Ответ: Lib_binsock: прием/отправка бинарных данных через сокет

Совершенно непонятно, в чем дело. Скорее всего, какие-то внутренние особенности реализации обработки данных. Не думаю, что с этим можно что-то сделать.
(Offline)
 
Ответить с цитированием
Старый 28.05.2012, 17:26   #14
LIDERSERVIS
Оператор ЭВМ
 
Регистрация: 20.10.2009
Сообщений: 49
Написано 2 полезных сообщений
(для 3 пользователей)
Ответ: Lib_binsock: прием/отправка бинарных данных через сокет

Сообщение от AssA Посмотреть сообщение
провел тест на LG ( gw300 ):

binsock.debug_register(0);
binsock.enable_debug(-1);

ansi:
отправил: 123фф123
на тел:123? ( len = 4 )
utf-8:
отправил: 123фф123
на тел: 123фф123 ( len = 8 )

......

то есть засада в функции binsock.read_bin() - мне кажется, когда присваивается результат, NOKIA и LG воспринимают это по-разному: нокиа строго раскладывает побайтно, lg в этом потоке бинарных данных рассматривает utf8 символы и преобразует находу. можно ли и NOKIA заставить "распознавать" строку UTF-8 ?

1. На Delphi :
Перевожу русские буквы в base64, и отправляю в сокет ...Socket.Connections[i].SendText(AnsiToBase64('ваш текст' + '@')),
где например @ --- дополнительно обозначаю конец текста

function AnsiToBase64(String):String;
var
        
SS string;
begin
        SS
:=Utf8Encode(S);
        
SS:=EncodeBase64(SS);
        
result:=SS;
end
где, Utf8Encode --- стандартная ф-ция библиотеки System

EncodeBase64 :
function EncodeBase64(ValueString): String;
const 
 
b64alphabetPChar 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  
padPChar '===='

  function 
EncodeChunk(const ChunkString): String
  var 
    
WLongWord
    
inByte
  
begin 
    n 
:= Length(Chunk); := 0
    for 
:= 0 to n do 
      
:= Ord(Chunk[1]) shl ((i) * 8); 
    
Result := b64alphabet[(W shr 18) and $3f] + 
              
b64alphabet[(W shr 12) and $3f] + 
              
b64alphabet[(W shr 06) and $3f] + 
              
b64alphabet[(W shr 00) and $3f]; 
    if 
<> 3 then 
      Result 
:= Copy(Result01) + Copy(pad0n); 
  
end

begin 
  Result 
:= ''
  while 
Length(Value) > do 
  
begin 
    Result 
:= Result EncodeChunk(Copy(Value03)); 
    
Delete(Value13); 
  
end
end
********************************************

2. На мобильном клиенте
Считываю данные,

Function ReadData():string;
var
        
kinteger;
        
S:string;
begin
            S
:='';
            
K:=0;
                        
            
i:=binsock.available;
            
            if 
i=(-1then
            begin
            
... ОШИБКА ПОЛУЧЕНИЯ ДАННЫХ
            end 
ELSE if i<>0 then
                                BEGIN
                                K
:=0;
                                
repeat
                                
while ((ConnectError=true) and (binsock.available<>0) and (chr(k)<>'@')) do
                                        
begin
                                        k 
:= binsock.read_byte;
                                        if 
k=(-1then 
                                                begin
                                                
... ОШИБКА ПОЛУЧЕНИЯ ДАННЫХ
                                                end 
else                                        
                                        if 
chr(k)<>'@' then S := chr(k);                                                                
                                        
end;
                                
until ((ConnectError=false) or (chr(k)='@'));
                                
END;
                                
            
ReadData:=S;                                                
end
Разкодирую данные в utf с помощью библиотеки proweb http://forum.boolean.name/showthread.php?t=8417
S:=base64_decode(S);
    
S:=encode(S'utf-8''ошибка'); 
P.S. Как правило работает на всех телефоннах
(Offline)
 
Ответить с цитированием
Старый 13.08.2012, 14:09   #15
Gonzo
Оператор ЭВМ
 
Аватар для Gonzo
 
Регистрация: 12.01.2011
Адрес: Воронеж
Сообщений: 32
Написано одно полезное сообщение
Ответ: Lib_binsock: прием/отправка бинарных данных через сокет

Возможно ли открытие одновременно более одного соединения?
(Offline)
 
Ответить с цитированием
Ответ


Опции темы

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

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

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
передача данных через GPRS Mirik1 MidletPascal 22 01.02.2010 21:17
Загрузка бинарных данных через сокеты Skythrone Прочие вопросы 3 20.08.2009 19:13
прием e-mail pop3 (sources) abcdef Основной форум 2 02.05.2009 19:42
Прогу для чтения бинарных файлов! ELIAS Blitz3D 9 15.03.2009 19:09
проблемма сокет соединения Aluk Основной форум 1 29.09.2007 20:27


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


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com