PHP функция pack() нужен аналог
От: BazaroffMA  
Дата: 04.04.07 20:07
Оценка:
Вещаюсь

немогу найти сабж, вот описание на PHP

string pack ( string format [, mixed args [, mixed ...]] )

Pack given arguments into binary string according to format. Returns binary string containing data.

The idea to this function was taken from Perl and all formatting codes work the same as there, however, there are some formatting codes that are missing such as Perl's "u" format code. The format string consists of format codes followed by an optional repeater argument. The repeater argument can be either an integer value or * for repeating to the end of the input data. For a, A, h, H the repeat count specifies how many characters of one data argument are taken, for @ it is the absolute position where to put the next data, for everything else the repeat count specifies how many data arguments are consumed and packed into the resulting binary string. Currently implemented are

Таблица 1. pack() format characters
Code Description
a NUL-padded string
A SPACE-padded string
h Hex string, low nibble first
H Hex string, high nibble first
c signed char
C unsigned char
s signed short (always 16 bit, machine byte order)
S unsigned short (always 16 bit, machine byte order)
n unsigned short (always 16 bit, big endian byte order)
v unsigned short (always 16 bit, little endian byte order)
i signed integer (machine dependent size and byte order)
I unsigned integer (machine dependent size and byte order)
l signed long (always 32 bit, machine byte order)
L unsigned long (always 32 bit, machine byte order)
N unsigned long (always 32 bit, big endian byte order)
V unsigned long (always 32 bit, little endian byte order)
f float (machine dependent size and representation)
d double (machine dependent size and representation)
x NUL byte
X Back up one byte
@ NUL-fill to absolute position

... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: PHP функция pack() нужен аналог
От: Danchik Украина  
Дата: 04.04.07 20:38
Оценка:
Здравствуйте, BazaroffMA, Вы писали:

[Skip]

А зачем? Что она делает я так и не понял.
Re[2]: PHP функция pack() нужен аналог
От: BazaroffMA  
Дата: 04.04.07 20:43
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Здравствуйте, BazaroffMA, Вы писали:


D>[Skip]


D>А зачем? Что она делает я так и не понял.


она преобразует набор аргументов в бинарную строку, мне эту строку нужно будет отправить на сервер (через сокет) в пхп выглядит так :

$str = pack("cV",5,'sometext').tounicode("admin");


tounicode — своя функция просто преобразует в юникод
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: PHP функция pack() нужен аналог
От: djs_ Россия  
Дата: 04.04.07 23:28
Оценка:
Здравствуйте, BazaroffMA, Вы писали:

BMA>Вещаюсь


BMA>немогу найти сабж, вот описание на PHP


Это шутка? Такой функции в Pascal/C нет.
Вы так сказать "смысл" этой функции в Perl/PHP понимаете?
--
Спасибо
Re[2]: PHP функция pack() нужен аналог
От: BazaroffMA  
Дата: 05.04.07 03:06
Оценка:
Здравствуйте, djs_, Вы писали:

_>Здравствуйте, BazaroffMA, Вы писали:


BMA>>Вещаюсь


BMA>>немогу найти сабж, вот описание на PHP


_>Это шутка? Такой функции в Pascal/C нет.

_>Вы так сказать "смысл" этой функции в Perl/PHP понимаете?

нету, это я уже понял.
Смысл понимаю, хотелось бы реализовать, или найти реализацию
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: PHP функция pack() нужен аналог
От: BazaroffMA  
Дата: 05.04.07 07:58
Оценка:
Ниужели никто неможет помоч?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: PHP функция pack() нужен аналог
От: OdesitVadim Украина  
Дата: 05.04.07 08:04
Оценка:
Здравствуйте, BazaroffMA, Вы писали:

BMA>Ниужели никто неможет помоч?

Кажись вам поможет функция Format. юзается приблезительно так
s:=format('test: %d q=%s',[i,'te']);
если i=9, то s = 'test: 9 q=te';
функция похожа очень на сишную sprintf()
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: PHP функция pack() нужен аналог
От: djs_ Россия  
Дата: 05.04.07 08:14
Оценка:
Здравствуйте, BazaroffMA, Вы писали:

BMA>нету, это я уже понял.

BMA>Смысл понимаю, хотелось бы реализовать, или найти реализацию

Так в том-то и дело, что Вам не надо её реализовывать.
Посылайте эти данные последовательно (write(scket, my_var_ptr, sizeof(my_var) [* length]), или опишите структуру данных, которые посылаете (struct/record) и спокойно посылайте.
Только учтите, что на удаленной стороне Вы не сможете отделить "sometext" от tounicode("admin").
И вы не уточнили, вам Pascal нужен, или С.
--
Спасибо
Re: PHP функция pack() нужен аналог
От: BazaroffMA  
Дата: 05.04.07 10:05
Оценка:
Нашел функцию
function StrFmt(Buffer, Format: PChar; const Args: array of const): PChar; overload;

StrFmt formats the series of arguments from an open array into a buffer.

Buffer is a buffer that receives the results.

Format is a null-terminated format string that indicates how to generate the results. For more information about how the result is formatted, see Format Strings.

Args is an array of arguments that replace the format specifiers in Format.

Args_Size gives the index of the last argument (one less than the number of elements in Args).

StrFmt returns a pointer to the destination buffer.

The first form of StrFmt is not thread-safe, because it uses localization information contained in global variables. The second form of StrFmt, which is thread-safe, refers to localization information contained in the FormatSettings parameter. Before calling the thread-safe form of StrFmt, you must populate FormatSettings with localization information. To populate FormatSettings with a set of default locale values, call GetLocaleFormatSettings.


Но вроде неподходит, колеги помогайте очень надо.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: PHP функция pack() нужен аналог
От: BazaroffMA  
Дата: 05.04.07 10:11
Оценка:
Здравствуйте, djs_, Вы писали:

_>Здравствуйте, BazaroffMA, Вы писали:


BMA>>нету, это я уже понял.

BMA>>Смысл понимаю, хотелось бы реализовать, или найти реализацию

_>Так в том-то и дело, что Вам не надо её реализовывать.

_>Посылайте эти данные последовательно (write(scket, my_var_ptr, sizeof(my_var) [* length]), или опишите структуру данных, которые посылаете (struct/record) и спокойно посылайте.
_>Только учтите, что на удаленной стороне Вы не сможете отделить "sometext" от tounicode("admin").
_>И вы не уточнили, вам Pascal нужен, или С.

воо, очень похоже на правду

вот код на пхп:
function ececute_action($name){
global $errors;
global $ip,$port;
        $id = get_id($name);
        $buf=pack("cV",5,$id).tounicode("execute");
        $socket=@fsockopen($ip,$port,$errno,$errstr,1) or die('not connected');
        fwrite($socket,pack("s",(strlen($buf)+2)).$buf);
                $len=unpack("v",fread($socket,2));
                $rid=unpack("c",fread($socket,1));
        for($i=0;$i<(($len[1]-4)/4);$i++)
                    {
                        $read=unpack("i",fread($socket,4));
                        $rs.=$read[1];
                    }
        fclose($socket);
                return GetError($rs);
}


приблизительно реалтзацию на Delphi если не затруднит, буду благодарен.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: PHP функция pack() нужен аналог
От: djs_ Россия  
Дата: 05.04.07 11:32
Оценка:
Здравствуйте, BazaroffMA, Вы писали:

BMA>Здравствуйте, djs_, Вы писали:


_>>Здравствуйте, BazaroffMA, Вы писали:


BMA>>>нету, это я уже понял.

BMA>>>Смысл понимаю, хотелось бы реализовать, или найти реализацию

_>>Так в том-то и дело, что Вам не надо её реализовывать.

_>>Посылайте эти данные последовательно (write(scket, my_var_ptr, sizeof(my_var) [* length]), или опишите структуру данных, которые посылаете (struct/record) и спокойно посылайте.
_>>Только учтите, что на удаленной стороне Вы не сможете отделить "sometext" от tounicode("admin").
_>>И вы не уточнили, вам Pascal нужен, или С.

BMA>воо, очень похоже на правду


BMA>вот код на пхп:

BMA>
BMA>function ececute_action($name){
BMA>global $errors;
BMA>global $ip,$port;
BMA>        $id = get_id($name);
BMA>        $buf=pack("cV",5,$id).tounicode("execute");
BMA>        $socket=@fsockopen($ip,$port,$errno,$errstr,1) or die('not connected');
BMA>        fwrite($socket,pack("s",(strlen($buf)+2)).$buf);
BMA>                $len=unpack("v",fread($socket,2));
BMA>                $rid=unpack("c",fread($socket,1));
BMA>        for($i=0;$i<(($len[1]-4)/4);$i++)
BMA>                    {
BMA>                        $read=unpack("i",fread($socket,4));
BMA>                        $rs.=$read[1];
BMA>                    }
BMA>        fclose($socket);
BMA>                return GetError($rs);
BMA>}
BMA>


BMA>приблизительно реалтзацию на Delphi если не затруднит, буду благодарен.


Если честно, на Delphi затруднит — паскаль знаю уже "по-наслышке".

// где unicode_str = tounicode("execute");
void * data_to_send = malloc(sizeof(int) + sizeof(id) + unicode_str_length);
void * ptr = data_to_send;

*((int *)ptr) = 5; 
ptr += sizeof(int);
*((long *)ptr) = long2le(get_id(...)); 
ptr += sizeof(long);
memcpy(ptr, unicode_str, unicode_str_length); 

// Теперь в data_to_send именно то, что вы и хотели получить посредством pack(). 
write(socket, data_to_send, sizeof(int) + sizeof(long) + unicode_str_length);


Со структурой было бы тоже самое:

typedef struct {
   int   c;
   long  id;
   char  unicode_str[MAX_LENGTH];
} Tdata_to_send;

Tdata_to_send  data_to_send;

// ....

data_to_send.c = 5;
data_to_send.id = long2le(get_id(...)); 
memcpy(data_to_send.unicode_str, unicode_str, unicode_str_length); // где unicode_str = tounicode("execute");

// Теперь в data_to_send именно то, что вы и хотели получить посредством pack(). 
write(socket, data_to_send, sizeof(int) + sizeof(long) + unicode_str_length);
// или
write(socket, data_to_send, sizeof(Tdata_to_send));


Или совсем просто (но не хорошо):

int c = 5;
white(socket, &c, sizeof(c));
write(socket, &id, sizeof(id));
write(socket, unicode_str, unicode_str_length); //подразумевается, что unicode_str имеет тип PChar, т.е. char *
--
Спасибо
Re[6]: PHP функция pack() нужен аналог
От: BazaroffMA  
Дата: 05.04.07 13:42
Оценка:
Здравствуйте, djs_, Вы писали:

_>Со структурой было бы тоже самое:


_>
_>typedef struct {
_>   int   c;
_>   long  id;
_>   char  unicode_str[MAX_LENGTH];
_>} Tdata_to_send;

_>Tdata_to_send  data_to_send;

_>// ....

_>data_to_send.c = 5;
_>data_to_send.id = long2le(get_id(...)); 
_>memcpy(data_to_send.unicode_str, unicode_str, unicode_str_length); // где unicode_str = tounicode("execute");

_>// Теперь в data_to_send именно то, что вы и хотели получить посредством pack(). 
_>write(socket, data_to_send, sizeof(int) + sizeof(long) + unicode_str_length);
_>// или
_>write(socket, data_to_send, sizeof(Tdata_to_send));
_>



Спасибо что возитесь со мной , выбрал этот вариант так как он более менее понятен . Но может ктонибудь переведет жто на паскаль.
long2le — что такое?
int в си это byte в паскале? (длинна 1 байт?)
memcpy = CopyMem как я понял
char = Pchar

--------

c signed char
V unsigned long (always 32 bit, little endian byte order)
----
Тоесть в итоге я должен собрать строку из
(signed char + unsigned long) + Pchar

может кто подробнее обьяснить как это сделать?

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

procedure TForm1.Button1Click(Sender: TObject);
type TDataToSend = record
   c:byte;
   id:Longint;
   UNIStr:PChar;
end;

var DTS:TDataToSend;
    l:integer;
    s:string;
begin
DTS.c:=5;
DTS.id:=3301;
s:=tounicode('admin');
l:=SizeOf(s);
DTS.UNIStr:=AllocMem(l);
CopyMemory(DTS.UNIStr,@s,l);
IdTCPClient1.Connect(-1);
While not IdTCPClient1.Connected do Application.ProcessMessages;
IdTCPClient1.Socket.Send(DTS.c,SizeOf(Integer));
IdTCPClient1.Socket.Send(DTS.id,SizeOf(LongInt));
IdTCPClient1.Socket.Send(DTS.UNIStr,SizeOf(DTS.UNIStr));
Application.ProcessMessages;
IdTCPClient1.Disconnect;
end;
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: PHP функция pack() нужен аналог
От: djs_ Россия  
Дата: 05.04.07 17:00
Оценка: 3 (1)
Здравствуйте, BazaroffMA, Вы писали:

BMA>long2le — что такое?

BMA>int в си это byte в паскале? (длинна 1 байт?)
BMA>memcpy = CopyMem как я понял
BMA>char = Pchar

Не совсем так. long2le — это я просто выдумал. Это типа htonl. Ну да это так, просто к слову.

int — это в паскале integer, обычно 4 байта.
char != PChar. PChar-у соответствует (char *), т.е. указатель.

BMA>--------


BMA>c signed char

BMA>V unsigned long (always 32 bit, little endian byte order)
BMA>----
BMA>Тоесть в итоге я должен собрать строку из
BMA>(signed char + unsigned long) + Pchar

Если "5" у вас укладывается, то да, signed char.
И третий член — совсем даже не PChar (иначе Вы и передадите всего лишь адрес, а не саму строку).
Третий слен структуры должен быть именно строкой (только не TString, а array of char [0..MAX_LENGTH]).

BMA>может кто подробнее обьяснить как это сделать?


BMA>п.с. то что у меня неработает выглядит так, все отсылает и никаких ошибок.


procedure TForm1.Button1Click(Sender: TObject);
type TDataToSend = record
   c: byte;
   id:Longint;
   UNIStr: array [1..255] of char;
   // Можно ли UNIStr: array of char ?
end;

var DTS:TDataToSend;
    l:integer;
    s:string;
begin
   DTS.c:=5;
   DTS.id:=3301;
   s:=tounicode('admin');
   l:=s.Length();
   if(l > 255) throw ... ; // Строка не поместится в UNIStr
   CopyMemory(DTS.UNIStr, s.c_str(), l); // вот тут не знаю, как правильно в паскале. 

   IdTCPClient1.Connect(-1);
   While not IdTCPClient1.Connected 
       do Application.ProcessMessages;
   IdTCPClient1.Socket.Send(DTS, SizeOf(TDataToSend));
   // или
   // IdTCPClient1.Socket.Send(DTS, SizeOf(byte) + SizeOf(long) + l);
   Application.ProcessMessages;
   IdTCPClient1.Disconnect;
end;


наверное примерно так.
--
Спасибо
Re[8]: PHP функция pack() нужен аналог
От: BazaroffMA  
Дата: 05.04.07 19:54
Оценка:
Здравствуйте, djs_, Вы писали:
_>наверное примерно так.

а вот и нет
наша с вами ошибка была вот в чем

1. неучитывалось старшинство разрядов
2. непередавалась длинна 1 байтом
в итоге сделал воттак:

type TDataToSend = array [0..255] of byte; 

var DTS:TDataToSend;
    i:integer;
    S,AdminID:string;
    UserId:Integer;
    Command:Word;
    Lh:byte;
//----------------
    Addr:TSockAddr;
    sock:TSocket;
begin

Command:=5;
UserID:=99999;
AdminID:=tounicode('admin');
//Length ОДИН БАЙТ
Lh:=Length(AdminID)+6;
DTS[0]:=Lh+1;
//command  ДВА БАЙТА
S:=IntToHex(Command,4);
DTS[1]:=StrToInt('$'+s[1]+s[2]);
DTS[2]:=StrToInt('$'+s[3]+s[4]);
//UserID  ПЕРЕВЕРНУТ! 3 БАЙТА
S:=IntToHex(UserID,6);
DTS[3]:=StrToInt('$'+s[5]+s[6]);
DTS[4]:=StrToInt('$'+s[3]+s[4]);
DTS[5]:=StrToInt('$'+s[1]+s[2]);
//AdminID СТРОКА В ЮНИКОДЕ 
For i:=0 to Length(AdminID) do DTS[i+6]:=ord(AdminID[i]);
//отправка данных
sock:=socket(AF_Inet,Sock_Stream,IPProto_IP);
Addr.sin_family:=PF_Inet;
Addr.sin_addr.S_addr:=Inet_Addr('172.29.1.13');
Addr.sin_port:=HtoNS(2012);
FillChar(Addr.sin_zero,SizeOf(Addr.sin_zero),0);
Bind(sock,Addr,SizeOf(Addr))=Socket_Error then
connect(sock,Addr,SizeOf(Addr));
For i:=0 to Lh do send(sock,DTS[i],1,0);
closesocket(sock);
end;


Огромнейшее вам спасибо, я тут новичек поставил "Супер", еще раз огромное спасибо, многие ошибки я неувидел изза незнания работы с сокетами, а многие изза непонимания функции pack()
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[9]: PHP функция pack() нужен аналог
От: djs_ Россия  
Дата: 05.04.07 22:50
Оценка:
Здравствуйте, BazaroffMA, Вы писали:

BMA>Здравствуйте, djs_, Вы писали:

_>>наверное примерно так.

BMA>а вот и нет

BMA>наша с вами ошибка была вот в чем

BMA>1. неучитывалось старшинство разрядов


Да, вы правы. Я long2le выдумал, а остальное как-то проморгал

BMA>2. непередавалась длинна 1 байтом


Если у вас сообщения разной длинный (как были закомментированные строки "или"), то длину пакета ставьте первой.
Тогда Вы сможете считать сразу длину, и потом, while (remain > 0) { read ...}
И хватит ли Вам 1 байта на Lh ?

А напишите структуру сообщения?

Я пока знаю, что это
struct {
int c; // не ясно, что. И int ли вообще
long id; // long в little-endian
char * command // Некая строка (команда) в unicode
};

И вот что еще имеет значение — Вы к "удаленной стороне" доступ имеете? Т.е. очевидно — нет, но на всякий случай
--
Спасибо
Re[10]: PHP функция pack() нужен аналог
От: BazaroffMA  
Дата: 06.04.07 07:37
Оценка:
Здравствуйте, djs_, Вы писали:

_>Здравствуйте, BazaroffMA, Вы писали:


BMA>>Здравствуйте, djs_, Вы писали:

_>>>наверное примерно так.

BMA>>а вот и нет

BMA>>наша с вами ошибка была вот в чем

BMA>>1. неучитывалось старшинство разрядов


_>Да, вы правы. Я long2le выдумал, а остальное как-то проморгал


BMA>>2. непередавалась длинна 1 байтом


_>Если у вас сообщения разной длинный (как были закомментированные строки "или"), то длину пакета ставьте первой.

_>Тогда Вы сможете считать сразу длину, и потом, while (remain > 0) { read ...}
_>И хватит ли Вам 1 байта на Lh ?
вполне и она собсно в данном конкретном случае фиксирована
длинна пакета максимум наверное в данном случае 255 байт

_>А напишите структуру сообщения?

0 байт длинна
2,3 команда
3,4,5, ID
6-19 #0A#0D#0M#0I#0N#0#0

_>Я пока знаю, что это

_>struct {
_> int c; // не ясно, что. И int ли вообще
нет, в паскале это WORD насколько я знаю в си тоже,
_> long id; // long в little-endian
little-endian младший в конце(завершающий) ?? в паскале это наверное просто неприсутсвует вобще.
_> char * command // Некая строка (команда) в unicode
_>};
тут да, скорее массив байт.

_>И вот что еще имеет значение — Вы к "удаленной стороне" доступ имеете? Т.е. очевидно — нет, но на всякий случай


имею, это сервер LineageII лайкофф, закрытый код есесно, ошибки он мне канечно показывает, но просто говорит что большой пакет и размер около 79000 байт.
но я такое не посылаю, тоесть это непойми что может даже не размер он просто пишет (Closed socket (xxx.xxx.xxx.xxx) Big packet size 78990) такчто где там запятая пропущена немогу знать

Если интересно могу здесь опубликовать метод работы с ним на пхп.
потомучто это одна из простейших функций выполняющихся удаленно.

Почему не сделать на пхп? на пхп уже сделано, и небезопасно, т.к. пхп это всетаки дырка.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.