Witam. Szukam juz troche po sieci i jakos dziwnie cicho. :-) Nie moge znalzc protokolu polchata, wie ktos moze skad go wziac ? W koncu troche botow czy innych programow powstalo, nie wierze ze ich autorzy siedzieli ze snifferem :-/
Istnieje pewien komponent do delphi który umożliwia komunikację z serwerem polchata, ale już go chyba nigdzie nie ma...
Autor ICeQ rzeczywiście siedział ze snifferem... reszta chyba także. Sam poszukuję protokołu. Jak znajdziesz jakiś artykuł, to chętnie bym poczytał.
Sam usiadlem ze snifferem a pozniej chyba mi sie znudzilo, teraz juz prawie nic nie pamietam ale to nie jest skomplikowane. Pamietam ze pomoglo mi jak zdekompilowalem zrodlo apletu polchatu. To byla oczywiscie masakra bo wszystkie zdefiniowane obiekty mialy nadane losowe nazwy.
Jesli chodzi o protokol to pakiety zbudowane sa nastepujaco:
naglowek - LLLLIISS
LLLL (4 bajty) - dlugosc calego pakietu lacznie z naglowkiem
II (2 bajty) - ilosc liczb w ciele
SS (2 bajty) - ilosc stringow w ciele
cialo - liczby, stringi
liczby - kazda po 2 bajty bez przerwy zgodnie z iloscia podana w naglowku
stringi - kazdy string ma postac LL...0
LL - dlugosc stringa ale nie znakow tylko bajtow
... - czesc wlasciwa stringa w UTF-8
0 - bajt zerowy nieuwzgledniony w LL
A jak by to zaimplementować w delphi?
czy może być coś takiego?:
type TPolchatPackage = class(TObject)
head : record
LLLL : array[1..4] of byte; // dlugosc calego pakietu z naglowkiem
II : array[1..2] of byte; // ilosc liczb w ciele
SS : array[1..2] of byte; // ilosc lancychów w ciele
end;
body : record
numbers : string; // kazda po 2 bajty
strings : string{unknown};
LL : integer; // dlugosc stringa (bajty)
UTF : string; // czesc wlasciwa w UTF-8
zero : byte;
end;
end;
nie jestem tylko pewny ciała...
szczerze mowiac to nie wiem ale zostaly mi szkice procedur do wysylania i odbierania pakietow, moze Ci cos pomoga, wiem ze dzialaja, mozna sie za ich pomoca na pewno zalogowac:
uses SimpleTcp;
type
TArString = array of string;
TArWord = array of Word;
const
SOI = SizeOf(Integer);
SOW = SizeOf(Word);
SOB = SizeOf(Byte);
procedure Rvrs(var Buf; Count: Integer);
var
S: string;
I: Integer;
begin
SetLength(S, Count);
Move(Buf, Pointer(S)^, Count);
for I := 0 to Count - 1 do
(PChar(@Buf) + I)^ := S[Count - I];
end;
function PolchatWrite(Sock: TTcpSocket; ArW: array of Word;
ArS: array of string): Boolean;
var
Bt: Byte;
Count: Word;
SoPck, I: Integer;
begin
for I := 0 to High(ArS) do
ArS[I] := AnsiToUTF8(ArS[I]);
Count := Length(ArW);
SoPck := SOI + (2 * SOW) + (Count * SOW);
for I := 0 to High(ArS) do
Inc(SoPck, SOW + Length(ArS[I]) + SOB);
I := SoPck;
Rvrs(I, SOI);
Dec(SoPck, Sock.Write(I, SOI));
Rvrs(Count, SOW);
Dec(SoPck, Sock.Write(Count, SOW));
Count := Length(ArS);
Rvrs(Count, SOW);
Dec(SoPck, Sock.Write(Count, SOW));
for I := 0 to High(ArW) do
begin
Rvrs(ArW[I], SOW);
Dec(SoPck, Sock.Write(ArW[I], SOW));
end;
Bt := 0;
for I := 0 to High(ArS) do
begin
Count := Length(ArS[I]);
Rvrs(Count, SOW);
Dec(SoPck, Sock.Write(Count, SOW));
Dec(SoPck, Sock.Write(ArS[I][1], Length(ArS[I])));
Dec(SoPck, Sock.Write(Bt, SOB));
end;
Result := SoPck = 0;
end;
function PolchatRead(Sock: TTcpSocket; var ArW: TArWord;
var ArS: TArString): Boolean;
var
Bt: Byte;
Count: Word;
SoPck, I: Integer;
begin
I := Sock.ReadAll(SoPck, SOI);
Rvrs(SoPck, SOI);
Result := (I = SOI) and (SoPck >= SOI + (2 * SOW));
if not Result then Exit;
Dec(SoPck, I);
Dec(SoPck, Sock.ReadAll(Count, SOW));
Rvrs(Count, SOW);
SetLength(ArW, Count);
Dec(SoPck, Sock.ReadAll(Count, SOW));
Rvrs(Count, SOW);
SetLength(ArS, Count);
for I := 0 to High(ArW) do
begin
Dec(SoPck, Sock.ReadAll(Count, SOW));
Rvrs(Count, SOW);
ArW[I] := Count;
end;
for I := 0 to High(ArS) do
begin
Dec(SoPck, Sock.ReadAll(Count, SOW));
Rvrs(Count, SOW);
SetLength(ArS[I], Count);
Dec(SoPck, Sock.ReadAll(ArS[I][1], Length(ArS[I])));
Dec(SoPck, Sock.Read(Bt, SOB));
end;
Result := SoPck = 0;
for I := 0 to High(ArS) do
ArS[I] := UTF8ToAnsi(ArS[I]);
end;
modul SimpleTCP mozna pobrac ponizej:
http://piechnat.w.interia.pl/SimpleTcp.pas
ale ja juz nie pamietam czy on jest skonczony :-D
A nie dało by się tego jakoś przedstawić w IdTcpClient albo zwykłym TCPClientSocket z D6? Z tym SimpleTCP jakoś się nie łapię.
W sumie to nawet w tym przypadku udało mi się nawiązać połączenie, ale miałem już lekki kłopot z tymi tablicami, oraz odbieraniem i wysyłaniem pakietów :(
Dobra, troche czasu minęło. Oto podpowiedź dla kolejnych ktorzy by szukali pomocy z budowa pakietow:
type TPolchatPacket = record
pDD : longword;
pII : word;
pSI : word;
PacketType : word;
INTs : TStringList;
STRs : TStringList;
end;
Albo krótko, na dobry początek budowa pakietu logującego (nie na podstawie TPolchatPacket):
// BEGIN //
DD DD DD DD 00 01 00 08 05 78 UU UU [string USER] 00 PP PP [string PASS] 00 00 00 00 00 RR RR [string ROOM] 00 AA AA [string AUTHLINK] 00 S1 S1 [string SERVER] 00 S2 S2 [string SERVER-STRING] 00 CC CC [string CLIENT] 00
// END //
DD DD DD DD - Długość pakietu ( w zupelnosci moze byc tez 00 00 DD DD)
PP - Długość nicka
RR - Długość pokoju
AA - Dlugosc linka
S1 - Długość nazwy hosta
S2 - Długość stringu z opcjami zaawansowanymi
CC - Informacja o kliencie
Dzięki temu możecie smiało się zalogować na polchat za pomoca zwyklego socketa poprzez Sendtext().
===
Natomiast budowa właściwego protokołu polchata wygląda następująco:
DD DD DD DD II II IS IS [INTs] [STRINGs]
STRING: DS DS STRING 00
Lub następująco z przykladem jednego inta i jednego stringa:
DD DD DD DD II II IS IS TP TP [INT] (...) [DS DS STRING 00] (...)
DD - Dlugosc pakietu
II - Ilosc Intow
IS - Ilosc Stringow
TP - Typ pakietu (pierwszy int)
INT - Dane liczbowe
DS - Dlugosc stringa
STRING - wartosc ciągu
Podstawowe typy pakietow (dla odbioru) to:
610: [display na czacie]
614: powitanie #1, param-string
615: JOIN
616: LEAVE
617: GUEST/UNGUEST & OP/UNOP
618: BUDDY/UNBUDDY
619: USERLIST
625: ROOM INFO
626: (Na wejsciu) kolory, conv-table, pokoje, etc.
630: Wchodzisz do pokoju
Hmm... brakuje czegos? Tak... nie ma procedure budujacych i rozkladajacych pakiety... no cóż. Odrobina myślenia Wam nie zaszkodzi ;)
Znacznie wiecej informacji o budowie i zastosowaniu protokolu znajdziecie pod adresem http://eter.sytes.net/polchatproto/
Jak to podlaczyc z tym modulem TCP
function PolchatWrite(Sock: TTcpSocket; ArW: array of Word;
ArS: array of string): Boolean;
to co za zmienna dac w Sock ? podczas wykonywania tej procedury. ma ktos przykladowya procedure po
wcosnieciu buttona zeby sie zalogowac do tego polchatu ?
Za ciosem.
Udalo mi sie polaczyc z polchatem uzylem dokladnie tych funkcji wyzej z kompnentami Socket.
Kiedy odbieram dane w OnRead wpisalem:
var
Bt: Byte;
Count: Word;
SoPck, I: Integer;
ArW: TArWord;
ArS: TArString
begin
I := Sock.ReadAll(SoPck, SOI);
Rvrs(SoPck, SOI);
Result := (I = SOI) and (SoPck >= SOI + (2 * SOW));
if not Result then Exit;
Dec(SoPck, I);
Dec(SoPck, Sock.ReadAll(Count, SOW));
Rvrs(Count, SOW);
SetLength(ArW, Count);
Dec(SoPck, Sock.ReadAll(Count, SOW));
Rvrs(Count, SOW);
SetLength(ArS, Count);
for I := 0 to High(ArW) do
begin
Dec(SoPck, Sock.ReadAll(Count, SOW));
Rvrs(Count, SOW);
ArW[I] := Count;
end;
for I := 0 to High(ArS) do
begin
Dec(SoPck, Sock.ReadAll(Count, SOW));
Rvrs(Count, SOW);
SetLength(ArS[I], Count);
Dec(SoPck, Sock.ReadAll(ArS[I][1], Length(ArS[I])));
Dec(SoPck, Sock.Read(Bt, SOB));
end;
Result := SoPck = 0;
for I := 0 to High(ArS) do
ArS[I] := UTF8ToAnsi(ArS[I]);
Teraz jest tak ze kiedy juz odczyta sie porcja danych W tablicy ArS i ArW w tablicy sa dane z pakietu. Wiec nizej wpisalem sobie tak:
For D := 0 to High(ArW) do Begin
memo1.lines.add('ArW'+inttostr(D)+': ' + IntToStr(ArW[D]));
ArrOfInts[D] := ArW[D];
End;
For D := 0 to High(ArS) do Begin
memo1.lines.add('TSr'+inttostr(D)+': ' + ArS[D]);
ArrOfString[D] := ArS[D];
Kiedy uzywam Memo1 i wyswietlam dane co tam sie odbiera jest OK
Kiedy jej nie ma wywala blad access violation
A takze kiedy wchodze na kanal gdzie jest malo osob jest ok
a jak wejde na kanal gdzie dostaje dluuuga liste USERLISt
wyskakuje mi blad Access violation.
Czy wiecie moze jak to rozwiazac by nie bylo problemow z odbieraniem tych danych?