Citat:
franjo_tahi: Ima kakav dio koda koji to radi da se može ovjde staviti?
Kada je u pitanju nacin koji se odnosi na TCP/IP protokol koji je savkic pomenuo, ima vise nacina koji su Delphiju odmah dostupni.
Ja rekoh da najcese koristim TServerSocket/TClientSocket, mada nije lose znati da su oni u novijim Delphi/C++ Builder verzjama 'depreciated' (ne popularisu se vise), iako su bili sasvim pouzdani. Ovo garantujem jer mi neki serveri zasnovani na njima rade godinama.
Ako nikada nisi koristio ove komponente, mozda je bolje da odmah pogledas kako bi se to uradilo u Indy preko TIdTCPClient/TIdTCPServer, jer je sva slozenost TCP/IP sakrivena unutar samih metoda (funkcija), dok kod TServerSocket/TClientSocket kompletan threading i kontrolu slanja/prijema buffera treba da radis sam. Ovo nije visa matematika, ali ipak treba implementirati nekoliko trikova, a za to treba odvojiti malo vremena da se apsolvira. (Inace, Delphi primer po ovom pitanju dovodi u zabludu, jer polazi od pretpostavke da se CEO buffer salje i CEO buffer prima ODJEDNOM, sto u TCP/IP praksi i standardu ne radi tako, ali da ne duzim).
U Indy-ju je princip vrlo jednostavan:
1. KLIJENT (onaj koji uspostavlja vezu) kao parametre treba da ima IP adresu SERVERA (onoga kome se salje) i zajednicki Port kojim ce se slati. IP adresa servera je "localhost" ako se radi o istom racunaru, odnosno "127.0.0.1". Port je obican Integer broj od 0 do 65535 (u novijim standardima i vise), izuzev nekih rezervisanih, mada se i oni mogu koristiti.
2. KLIJENT pokusava da uspostavi vezu.
3. Ako SERVER nije aktivan odgovarajucim Eventom ces lako na KLIJENTU resiti nastalu situaciju i pokusati po potrebi ponovo.
4. Ako je SERVER aktivan, bice spreman da prima sve sto mu salje KLIJENT, naravno treba da se isprogramira prijem.
5. Svaka moguca greska se moze uhvatiti i na SERVERU.
6. SERVER prima Buffer, a po ISTOJ, VEC USPOSTAVLJENOJ VEZI moze nazad po potrebi da vrati neki podatak.
7. Sta ce se raditi s primljenim podacima, to je na programeru...
Postoje brojne metode (funkcije) za prijem/slanje, a koju ces koristiti, zavisi od potrebe.
U ovom primeru, KLIJENT salje sting serveru, SERVER prima string, i salje po vec uspostavljenoj konekciji datum&vreme na serveru. Sve se belezi u Memo.
Kod je na C++ Builder-u, ali je sve sam VCL pa ces se lako snaci.
(Nemoj da te zbuni zasto prvo saljem duzinu Stringa pa tek onda String. To je moj stil i profesionalna deformacija i ne mora tako. Verovatno moze i 'odjednom' sa WriteBuffer, probaj)
--- KLIJENT ---
Code:
void __fastcall TIndy9ClientForm::AskButtonClick(TObject *Sender)
{
AskButton->Enabled = false;
try
{
IdTCPClient->Connect(5000);
AnsiString REQUEST = "Can you please tell me what's the time?";
Memo->Lines->Add( REQUEST + " (prepared)" );
IdTCPClient->WriteInteger( REQUEST.Length() );
IdTCPClient->Write( REQUEST );
Memo->Lines->Add( REQUEST + " (sent)" );
int BytesToRead = IdTCPClient->ReadInteger();
AnsiString RESPONSE = IdTCPClient->ReadString( BytesToRead );
Memo->Lines->Add( RESPONSE );
}
__finally
{
IdTCPClient->Disconnect();
AskButton->Enabled = true;
}
}
--- SERVER ---
Code:
void __fastcall TIndy9ServerForm::IdTCPServerExecute(
TIdPeerThread *AThread)
{
int BytesToRead = AThread->Connection->ReadInteger();
AnsiString REQUEST = AThread->Connection->ReadString( BytesToRead );
Memo->Lines->Add( REQUEST + " (received)" );
AnsiString RESPONSE = FormatDateTime( "hh:mm AM/PM", Now() );
Memo->Lines->Add( RESPONSE + " (prepared)" );
AThread->Connection->WriteInteger( RESPONSE.Length() );
AThread->Connection->Write( RESPONSE );
Memo->Lines->Add( RESPONSE + " (sent)" );
}
void __fastcall TIndy9ServerForm::IdTCPServerStatus(TObject *ASender,
const TIdStatus AStatus, const AnsiString AStatusText)
{
Caption = AStatusText;
}