PDA

View Full Version : برنامه نویسی شبکه ( راهنمای گام به گام Indy ) - بخش اول



www2006
دوشنبه 13 شهریور 1385, 15:26 عصر
بسمه تعالی


با عرض سلام خدمت همه دوستان عزیز


هدف بنده از نوشتن این مقاله شروع بحثی درباره برنامه نویسی شبکه توسط Indy در محیط دلفی است.امیدوارم دوستان باتجربه تر در مفید تر شدن این نوشته همکاری کنند .


بدون حاشیه مستقیم سراغ اصل مطلب میروم ...

Indy TCP/IP server Component
شاید فکر کنید که از قسمت سخت Indy Component شروع میکنیم ، در واقع درست فکر میکنید چون وقتی ساختن یک client را (در مقالات بعدی ) ببنید متوجه میشوید که ساخت یک client چقدر ساده است .

برای شروع ، یک پروژه جدید ( New Project ) ایجاد کرده ویک IdTcpServer component در آن قرار دهید .( این کامپوننت در برگه Indy Server قرار دارد و اولین کامپوننت است)
تنظیمات زیر را روی آن اعمال نمایید :

Property Name : Property Value
Active : True
DefaultPort : 1001
Greeting Text : hello


خوب ... Tcp server شما آماده کار است! بدون اینکه حتی یک خط هم کد نوشته باشید . اگر برنامه خود را اجرا کنید فقط یک صفحه خالی نشان میدهد. برنامه را در حالت Run نگه دارید. برای تست سرور از telnet استفاده میکنیم ( خیلی ساده است ...! اگر مقاله را دنبال کنید)


کافیست در Command Prompt تایپ کنید :

c:\> telnet 127.0.0.1 1001

که عدد 127.0.0.1 ip محلی شماست و 1001 هم شماره پورتی است که قبلا ست کرده اید.


بعد از زدن کلید Enter پیغام hello از طرف سرور برای شما ارسال میشود .(پس ارتباط شما با سرور از پورت 1001 به درستی برقرار شده است .)
در ضمن فراموش نکنید که برنامه ای که برای سرور نوشته اید حتما باید run شده باشد ( یا بهتر بگویم باید در حال اجرا باشد .)

پیغام hello که برای شما ارسال شده است در واقع همانGreeting Text property است که شما ست کرده اید پس هر پیغام دیگری میتواند باشد .

حالا میخواهم برنامه سروررا کمی توسعه دهم. میخواهیم سرور در برابر دستورات ما عکس-العمل نشان دهد .مثلا با تایپ دستور " Responde "، سرور پاسخ دهد که :
" Ok ! I have Responded "

این در واقع اولین اجرای دستورات است .

برای این کار ابتدا مقدار CommandHandlersEnabled را برابر True قرار دهید . سپس روی CommandHandlers property دوبار کلیک کنید و در پنجره ای که باز میشود روی AddNew کلیک کنید . روی Item ای که اضافه میشود کلیک کرده و تنظیمات زیر را روی Property های آن اعمال کنید :


Command : Responde
ReplyNormalText : ok! I have Responded


برنامه را کامپایل و اجرا کنید ... سپس مجدد telnet را مانند قبل اجرا کنید و بعد از دریافت پیغام اولیه ، Respode را تایپ کرده و Enter را بزنید .خواهید دید که پیغام مورد نظر بعنوان پاسخ برگردانده میشود .



در مقاله بعدی ابتدا کمی بیشتر در نحوه ایجاد ارتباط توسط سرور دقیق خواهیم شد و سپس سرور خود را توسعه خواهیم داد .



موفق باشید ...

www2006
دوشنبه 13 شهریور 1385, 16:46 عصر
اجازه دهید قبل از اینکه برنامه سرور را توسعه دهیم ، نگاهی دقیقتر داشته باشیم به معماری داخلی Indy server . ( البته فرض می شود که خوانندگان عزیز با مفهوم MultiThreading آشنایی مقدماتی را دارند. ) بعد از این بخش شما تقریبا تمامی جنبه های رفتاری یک Indy Server را خواهید فهمید .


تمام نود های فرزند یک TIDTcpServer دارای رفتار زیر هستند :
وقتی یک client به سرور متصل میشود ، thread ای که listener نام دارد (و کار آن هم دقیقا همان است که از نام آن بر می آید یعنی دایما در حال گوش دادن است تا ایجاد یک ارتباط جدید که توسط یک client ایجاد شده است را تشخیص دهد ) یک thread جدید ایجاد کرده و وظیفه Handle کردن تمام رخدادهای مربوط به این ارتباط را به آن thread واگذار میکند . پس در معماری داخلی یک سرور دو نوع thread وجود دارد : یکی Listener است که دایم در حالت انتظار برای ایجاد یک ارتباط جدید است و دیگری که بعد از ایجاد Connection بوجود می آید و کلیه وظایف ارتباطی بعهده اوست .


این معماری زیاد جالب نیست چون client ها هر وقت که بخواهند (بدون توجه به اینکه ممکن است سرور مشغول رسیدگی به دهها درخواست رسیده دیگر باشد ) میتوانند به سرور متصل شوند .
زیاد نگران نباشید .... چون برای این که بتوان تعداد thread های ایجاد شده را کنترل کرد راه حلهایی وجو د دارد ...
thread های نوع دوم ( آنهایی که listener نیستند ) را به دو شکل میتوان مدیریت کرد :


TIdThreadMgrDefault and TIdThreadMgrPool



قبل از اینکه در باره این دو مدل مدیریت thread ها و نحوه استفاده آنها توضیح دهم میخواهم خود IDThreadDefault و IDThreadPool را خیلی خلاصه معرفی کنم ...


IDThreadDefault همان حالت پیش فرضی است که اگر ما هیچ تنظیمی را اعمال نکنیم ، اعمال میشود یعنی برای هر Connection یک thread بطور مجزا ایجاد میشود و هنگام خاتمه ارتباط (Disconnect) شدن از بین میرود .(Destroy)


اما دومی (IDThreadPool) برای سرور هایی طراحی شده است که میخواهند بازدهی بالاتری داشته باشند . حافظه گرفتن و آزاد کردن آن عملی وقت گیر است به همین دلیل در حالت دوم استخری از thread ها (هرتعداد thread ای که شما تعیین کنید ) حافظه allocate میشود و در طول برنامه دیگر عمل گرفتن و آزاد کردن حافظه نخواهیم داشت .


این کل مفاهیم Thread ها در Indy بود .(ساده و سریع)


حتما میخواهید بدانید که چطور می توانید مدل thread ای را که میخواهند استفاده کنید را انتخاب کنید. خیلی ساده ... در برگه ی (Tab ( Indy misc شما هر دو نوع


TIdThreadMgrDefault and TIdThreadMgrPool


را مشاهده میکنید . کافیست هر کدام را که میخواهید روی فرم خود قرار داده و در
ThreadMgr Property ی سرور ( IdTCPServer1 ) آن را بعنوان مقدار وارد کنید .


امیدوارم خسته نشده باشید ... مطالب بعدی ساده تر و عملی تر هستند .


موفق باشید ....

حامی2
سه شنبه 14 شهریور 1385, 08:23 صبح
با سلام و تشکر از مطالب مفیدتان
اما من یه سوال پیشرفته تر دارم و اینکه چگونه از یک کامپیوتر و از طریق شبکه می شود از روی یک کامپیوتر دیگر فایلی را باز کرد و نمایش داد مثلا فیلمی را از کا مپیوتر دیگری روی کامپیوتر خودتان ببینید ؟
این کار با استفاده از ویندوز ساده است اما با ابزار Indy می شود یا خیر؟

www2006
سه شنبه 14 شهریور 1385, 09:13 صبح
با سلام
با استفاده از ابزارهای Indy میتوان برای client ها فایلی را ارسال کرد و یا بر عکس .حتی می توان به برنامه های در حال اجرای کاربران هم دسترسی داشت و آنها را کنترل کرد. اما درباره اینکه بتوان وارد کامپیوتر کاربر شد و از فایلهای موجود در آن استفاده کرد(مثلا یک فایل تصویری را اجرا کرد)، من اطلاعی ندارم .

www2006
سه شنبه 14 شهریور 1385, 10:43 صبح
بعد از آشنایی کلی با مفاهیم Threading در Indy ، در این بخش می خواهم کمی بیشتر در باره TIDTcpServer Component صحبت کنم .

یک سرور را میتوانیم در دو مد مختلف برنامه ریزی کنیم :

مد اول :
مد اول استفاده از CommandHandlers است . نوشتن سرور در این حالت بسیار ساده است . این مد را با مثال توضیح میدهم تا فهم آن ساده تر و سریعتر باشد :
فرض کنید که می خواهیم سروری داشته باشیم که در برابر دو دستور Hello و Add عکس العمل مناسب را انجام دهد . در برابر کلمه " Hello " ، کلمه " Hi " را برگرداند. اما دستور " Add " کمی متفاوت است چون میخواهیم با فرستادن چندین عدد به همراه دستور add حاصل جمع آنها را بدست آوریم .فرمت کلی دستور ارسالی ما به سرور به این شکل است :


add no1 no2 .... noN



و سرور حاصل جمع " no1 + no2 + .... + noN " را برخواهد گرداند .


مانند مثال اول یک TIDTcpServer روی فرم خود قرار دهید ( یا یک پروژه جدید باز کنید ویا از همان سرور قبلی استفاده کنید یعنی روی یک فرم دو کامپوننت TIDTcpServer نباشد ) . تنظیمات سرور دقیقا همانهایی است که در بخش اول ذکر شده است . حالا روی CommandHandlers دو بار کلیک کرده و در پنجره جدید دو Item جدید ایجاد کنید . برای Item اول مقادیر زیر را ست کنید :


Command : Hello
ReplyNormal : Hi


برای Item دوم هم مقدار Command را برابر کلمه " Add " قرار دهید و ...
حالا باید یه چند خطی کد نویسی کنید !


در قسمت Event های Item دوم روی OnCommand دوبار کلیک کنید تا وارد محیط کدنویسی شوید :





procedure TForm1.IdTCPServer1CommandHandlers1Command(ASender : TIdCommand);
var
i:integer;
f:float;
begin
f:=0;
for i:=0 to ASender.Params.Count-1 do
f:=f+strtofloat(ASender.Params[i]);
ASender.Thread.Connection.Writeln(floattostr(f));
end;



به همین سادگی !
حالا برنامه را کامپایل و اجرا کنید . ( در حالی که برنامه شما Run است ) Telnet را با همان دو مقدار قبل ( یعنی با IP ی 127.0.0.1 و پورت 1001 ) فراخوانی کرده و سرور را تست کنید .

( ما تا حالا هیچ فکری برای Handle کردن error های احتمالی نکرده ایم ... چون فعلا هدف ما آموزش مفاهیم است نه نوشتن یک برنامه بی عیب و ایراد )

اگر مجدد به کدی که نوشته اید نگاه کنید مشاهده خواهید کرد که :
1- ما از یک Property ی ناآشنا به نام Asender استفاده کردیم .
2- Asender ،دارای یکسری Property است مثل Connection و یا Params .
3- نهایتا ما برای ارسال string به Tcp/Ip connection از متد Writeln استفاده کردیم .

منظور ؟ :
Asender در واقع همان Client ای است که به ما connect شده است . مطلبی که در باره Thread ها گفتم را که هنوز فراموش نکرده اید ؟ برای هر Client بلافاصله بعد از Connect شدن یک Thread جدید ایجاد میشود . در مورد بالا هم Asender در واقع نمایانگر client ای است که به سرور ما متصل شده است . Asender دارای Property های زیادی است که مهمترین آنها Connection است که درواقع پل ارتباطی ما با کاربر است .توسط آن ما میتوانیم یک String یا Integer ویا حتی یک Record را برای client ارسال کنیم .


در مقاله بعدی مد دوم را برای سرور بررسی میکنم و سعی خواهم کرد در باره client ها هم مطالبی رو بگم .
با Indy همراه باشید ....

www2006
سه شنبه 14 شهریور 1385, 10:53 صبح
Indy یک پروژه OpenSource است . اگر در دلفی5 وجود ندارد می توانید آن را از :

http://www.indyproject.org/Sockets/Download/Files/Indy10.en.aspx

بطور رایگان دانلود کنید .

www2006
چهارشنبه 15 شهریور 1385, 14:50 عصر
سلام


همانطور که در انتهای بخش قبل قول داده بودم ، میخواستم درباره حالتی از سرور صحبت کنم که به طور اتومات دربرابر Command های کاربر عکس العمل نشان نمیدهد (مد دوم) ولی بنا به دلایلی این بحث را به آینده موکول میکنم .


امروز درباره کامپوننت TIDTcpClient توضیح خواهم داد :


اگر سه بخش قبل را فهمیده باشید ، فهمیدن این قسمت زیاد وقت شما را نمیگیرد.کافیست یک کامپوننت TIDTcpclient (در برگهIndy Client ، اولین کامپوننت است ) را روی فرم جدیدی که ایجاد کرده اید قرار دهید تا 80 درصد راه ساخت client را طی کرده باشید ..!
20 درصد باقیمانده موضوع این بخش از مقاله است .


سروری که در بخش قبل ایجاد کردیم را به خاطر بیاورید .. دو دستور داشت به نامهای Hello و Add . میخواهیم client خود را برای برقراری ارتباط با این سرور تنظیم کنیم.



روی فرم خود علاوه بر کامپوننت TIDTcpClient دو Button ویک Tlistbox هم قرار دهید . در این Listbox شما مقادیری که برای عمل جمع به سرور ارسال خواهید کرد را قرار خواهید داد . حالا باید مقادیر پورت ( Port ) و Host را برای TIDTcpClient ست کنید .


Port همان است که برای سرور قرار داده اید ( در مثال ما 1001 است ).


اما Host :
اگر می خواهید برنامه client را در همان کامپیوتری اجرا کنید که سرور هم روی آن اجرا میشود مقدار Host را برابر 127.0.0.1 قرار دهید وگرنه مقدار آن را برابر با IP کامپیوتر سرور قرار دهید .


ابتدا دستور Hello :

روی اولین button دوبار کلیک کرده و کد زیر را وارد کنید :





procedure TForm1.Button1Click(Sender:TObject);
begin
with IdTcpClient1 do
begin
connect;
Writeln('Hello');
ShowMessage(Readln);
Disconnect;


end;

end;








حالا برنامه را اجرا کنید ( فراموش نکنید که همواره قبل از اجرای برنامه Client حتما باید برنامه سرور را Run کرده باشید وگرنه با پیغام " Socket Error #10061" مواجه خواهید شد ). اگر تمام مراحل را بدرستی طی کرده باشید باید پیغام "Ok, I have responded" دریافت کنید .




حالا نوبت دومین دستور است . اینبار روی دومین button دوبار کلیک کرده و قطعه کد ساده زیر را وارد کنید :





procedure TForm1.Button2Click(Sender:TObject);

var



command: string;

i:integer;
begin
command:='Add';


for i:=0 to ListBox1.Items.Count -1 do
command:=command+' '+ListBox1.Items[i];

with IdTcpClient1 do
begin
connect;
Writeln(command);
ShowMessage(Readln);
Disconnect;
end;
end;















تنها تفاوت آن با قبلی این است که در اینجا ما دستور add را با پارامترهایی که در listbox وارد کرده اید ترکیب کرده و حاصل را که یک String است برای سرور ارسال میکنیم.
















نکته :



هنگام ارسال و دریافت یک پیغام بین Client و Server حتما به ترتیب متد های ارسال دقت لازم را داشته باشید .. مثلا اگر در سمت سرور چیزی مانند زیر داشتید :





WriteStream (...);
Writeln(...);
ReadStream(...);





در سمت کلاینت باید به این ترتیب باشد :





ReadStream(...);

ReadLn;
WriteStram(...);




در حالات دیگر ( اگر ترتیب را رعایت نکنید ) قادر به برقراری درست ارتباط نخواهید بود.





خوب ... کار Client هم تمام شد . در واقع مطالب مقدماتی ای که فکر میکردم برای شروع کار لازم دارید (تا حد امکان ساده و سریع ) تمام شد .



منبع اصلی این نوشته را ( که البته بنده سعی کردم ترجمه ای ساده و خلاصه از آن داشته باشم ) می توانید در سایت Delphi3000.com پیدا کنید .




موفق باشید ...

یاسر مددیان
یک شنبه 19 شهریور 1385, 10:22 صبح
دوست عزیز نمی خوای ادامه بدی ؟
بیا یه مسنجر طراحی کنیم با دلفی .

با تشکر

siavashr
یک شنبه 19 شهریور 1385, 10:26 صبح
سلام.
من هم یاد میگیرم اگر کمکی هم از دستم بر بیاد درخدمت هستم.
سیاوش راد

www2006
یک شنبه 19 شهریور 1385, 11:36 صبح
دوست عزیز نمی خوای ادامه بدی ؟

حتما ... البته با کمک دوستان ، چون مبحث خیلی گستردست .

با طراحی یک مسنجر ساده شروع کنیم ...

یاسر مددیان
یک شنبه 19 شهریور 1385, 12:04 عصر
عالیه
البته آقای سرباززاده پیش دستی کردن و یه سورس گذاشتن که از اینجا ازشون تشکر می کنم . من دارم دانلود می کنم .

مرسی .

www2006
یک شنبه 19 شهریور 1385, 13:48 عصر
بسمه تعالی


بعد از مفاهیم مقدماتی و پایه ای ( که علیرغم سادگی اهمیت فوق العاده ای دارند ) میخواهم ایجاد یک Messenger ساده ( که شامل یک سرور است و می تواند با client خود تبادل اطلاعات کند(در اینجا فقط string)) را آغاز کنم .


البته در همین ابتدای کار یاد آور شوم که زحمت Handle کردن Exception ها و توسعه برنامه گردن خوانندگان عزیز است چون نمیخواهم با کد های اضافه از خوانایی برنامه کاسته شود .



ابتدا سمت سرور :


مطابق شکل ، کامپوننت های زیر را روی فرم اولیه خود قرار دهید :


TIDTcpServer و memo و edit و button


http://barnamenevis.org/forum/attachment.php?attachmentid=4940&stc=1&d=1157878987



حالا تنظیمات زیر را برای TIDTcpServer اعمال کنید :


Active : true
DefaultPort : 5000



یک متغیر سراسری به صورت زیر تعریف کنید :

mythread : TIdPeerThread ;

(دلیل استفاده من از این متغیر حفظ اطلاعات Connection ایجاد شده است . اگر کسی راه مناسبتری بلد است ،خوشحال میشوم من را هم راهنمایی کند .)
این متغیر را در متد onConnect سرور IdTcpserver1 مقدار دهی میکنیم :



procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
begin
mythread := athread ;
end;





سپس در قسمت event ها روی onExecute دو بار کلیک کرده و :




procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
begin
Memo1.Lines.Add(AThread.Connection.ReadLn()) ;
end;


نکته 1 - متد onExecute هرگاه که از طرف Client چیزی برای سرور ارسال شود اجرا میشود ، پس برای دریافت پیغام client مناسبترین متد است .

نکته 2 - اگر میخواهید هنگام connect شدن Client عمل خاصی انجام دهید ( مثلا چیزی مثل Authentication ) میتوانید از متد onConnect استفاده کنید که فقط یکبار و آن هم هنگامی که یک کاربر به سرور متصل میشود اجرا میشود .

نکته 3 - همانطور که قبلا هم گفتم هنگام اتصال کاربر به سرور یک Thread جدید ایجاد میشود ، Athread همان thread ایجاد شده است .


سرور آماده دریافت اطلاعات کاربر و نمایش آن در داخل Memo1 است . ( میتوانید با telnet آن را امتحان کنید)

برای ارسال پیغام خود به Client ( پیغامی که داخل Textbox نوشته اید ) کافیست کد زیر را در متد onClick دکمه ( Button1 ) وارد کنید :




procedure TForm1.Button1Click(Sender: TObject);
begin
mythread.Connection.WriteLn(Edit1.Text);
end;




خوب اگر از telnet برای امتحان صحت عملکرد سرور خود استفاده کنید خواهید دید که میتوانید به راحتی عملی مانند chat را با سرور داشته باشید .


حالا نوبت client است . ایجاد client را در بخش بعد خواهم گفت . ( البته اگر عجله دارید خودتان شروع کنید چون با همین معلومات هم میتوان client ای طراحی کرد که با سرور ما کار کند.خیلی ساده است ..! )


موفق باشید ....

www2006
دوشنبه 20 شهریور 1385, 14:57 عصر
سمت کلاینت :


روی فرم جدیدی که برای Client ایجاد کرده اید ، کامپوننت های زیر را ( مطابق شکل ) قرار دهید :



http://barnamenevis.org/forum/attachment.php?attachmentid=4955&stc=1&d=1157975332



TIDTcpClient و memo و button_send و edit_Message
و
Edit_ServerIP و Edit_ServerPORT و Button_Connect



در اولین Editbox که Edit_ServerIP میباشد ، آدرس IP کامپیوتر سرور و یا نام NetBios ای آن را وارد میکنیم و داخل Edit_PORT هم شماره پورت . ( که البته مقدار آن را بصورت پیش فرض طوری قرار داده ام که با پورت 5000 از سروری که در همین کامپیوتر Run شده است ارتباط برقرار کند .)


حالا روی Button_Connect دو بار کلیک کرده و :




procedure TForm1.Button_connectClick(Sender: TObject);
begin
IdTCPClient1.Host := Edit_serverIP.Text ;
IdTCPClient1.Port := StrToInt(Edit_serverPORT.Text) ;
IdTCPClient1.Connect();
Button_connect.Enabled := False ;
end;



کار دستورات بالا واضح است( بعد از ست کردن Property های کلاینت ، ارتباط را با سرور برقرار میکنند ). آخرین دستور هم باعث جلوگیری از ارسال مجدد درخواست Connect میشود .


تا الان کار ایجاد ارتباط بین برنامه Client و Server انجام شده است . فقط باید بتوانیم پیغامهای سرور را دریافت و پاسخ دهیم . کافیست Timer ای روی صفحه قرار دهیم (تب System ، اولین کامپوننت ) تا به محض ارسال پیغام از طرف سرور از آن مطلع شویم . کد زیر را هم در onTimer مینویسیم :





procedure TForm1.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := False ;
try
Memo1.Lines.Add(' Server: ' + IdTCPClient1.ReadLn());
except on E:Exception do Form1.Close ;
end ;
Timer1.Enabled := True ;
end;



نکته بسیار مهمی که وجود دارد این است که حتما از کامپوننت IDAntiFreeze ( تب Indy misc ، دومین کامپوننت )در کلاینت خود استفاده کنید . ( دلیل آن را میتوانید در لینک زیر پیدا کنید .)

http://barnamenevis.org/forum/showthread.php?t=9385&page=2

خوب پیامهای سرور را هم دریافت کردیم ... حالا ارسال پیغام به سرور .

روی Button_send دو بار کلیک کنید و :




procedure TForm1.Button_sendClick(Sender: TObject);
begin
IdTCPClient1.WriteLn(Edit_message.Text);
end;




کار messenger ساده ما تمام شد .


در ضمن کد های این برنامه را ( البته با تغییرات خیلی جزیی ) میتوانید از آدرس زیر دریافت کنید :

http://barnamenevis.org/forum/attachment.php?attachmentid=4954&stc=1&d=1157975332





موفق باشید ...

Mahdi_S_T
دوشنبه 20 شهریور 1385, 15:18 عصر
من یه برنامه دیدم که با دلفی بود و این امکان رو داشت که به یاهو متصل بشه و وب کم کاربران رو ببینه در مورد این موارد هم مثال بزنید ممنون میشم.

Touska
سه شنبه 21 شهریور 1385, 13:55 عصر
من یه برنامه دیدم که با دلفی بود و این امکان رو داشت که به یاهو متصل بشه و وب کم کاربران رو ببینه در مورد این موارد هم مثال بزنید ممنون میشم.

بابا کم کم به اونجا هم می رسیم ، بنده خدا خیلی دارن خوب توضیح میدن پله پله :خجالت:

اگه بتونید در کنارش توضیح مختصری از UDP رو هم بدید کاملتر میشه :کف:

www2006
چهارشنبه 22 شهریور 1385, 11:27 صبح
اگه بتونید در کنارش توضیح مختصری از UDP رو هم بدید کاملتر میشه :کف:

چشم .... حتما ...
فقط ما منتظر مطالب سایرین هم هستیم

یاسر مددیان
پنج شنبه 23 شهریور 1385, 10:19 صبح
www2006 جان دستت درد نکنه .:خجالت:

seyed_farid
پنج شنبه 23 شهریور 1385, 14:22 عصر
من میخوام سه کامپیوتر رو به هم شبکه کنم. دو تا بعنوان سرور و یکی بعنوان کلاینت. سرورها بصورت main و Standby باشند و برنامه کلاینت با هردوی آنها ارتباط داشته باشه. دوستان میتونند کمکی کنند در این زمینه؟

Touska
شنبه 25 شهریور 1385, 11:40 صبح
من میخوام سه کامپیوتر رو به هم شبکه کنم. دو تا بعنوان سرور و یکی بعنوان کلاینت. سرورها بصورت main و Standby باشند و برنامه کلاینت با هردوی آنها ارتباط داشته باشه. دوستان میتونند کمکی کنند در این زمینه؟

ارتباط به چه شکل و چه جوری - بیشتر توضیح دهید ؟ :متفکر:

www2006
یک شنبه 26 شهریور 1385, 16:00 عصر
بسمه تعالی







مقدمه


همانطور که می دانید پروتکل Udp یکی از دو پروتکل اصلی لایه انتقال ( Transprot layer ) در پروتکل TCP/IP است . پروتکل دیگر این لایه TCP می باشد (که قبلا کمابیش در باره نحوه کار آن صحبت کرده ام).در این مقاله میخواهم کمی در باره پروتکل Udp و نحوه ی استفاده از آن در دلفی صحبت کنم.





تفاوتهای پروتکل های Tcp و Udp ( از نظر مفاهیم شبکه ) :


TCP: این پروتکل امکان ایجاد ارتباطات قابل اطمینان و اتصال گرا را فراهم می نماید. برخی از وظایف مربوط به این پروتکل به قرار زیر می باشد:
• شکستن و تقسیم بندی داده ها و پشته های دریافتی از لایه بالاتر به بسته های TCP و ساخت مجدد پشته ها از بسته های TCP در مقصد .
• حصول اطمینان از رسیدن بسته ها به مقصد .
• بازبینی بسته ها و مرتب کردن آنها و کنترل خطا
• کنترل جریان داده ها
UDP: این پروتکل برای فراهم آوردن مکانیزمی جهت کاهش و کم کردن سرریز داده ها در انتقال اطلاعات بکار می رود و معمولا برای ارتباطاتی که نیاز به قابلیت اطمینان ندارند استفاده می شود. لایه انتقال در سطح بالای خود با لایه کاربرد در ارتباط است.داده های تحویلی به لایه کاربرد توسط برنامه های کاربردی قابل دریافت می باشد ، همچنین این برنامه ها می توانند با استفاده از APIها ( Application Program Interface ) مستقیما با لایه انتقال ارتباط برقرار کنند .



تفاوتهای پروتکل های Tcp و Udp ( در Indy ) :

Tcp در یک نگاه :
در ابتدا نگاهی داریم به جزییات Tcp . قبل از اینکه بتوانیم از طریق Tcp اطلاعاتی ردوبدل کنیم ، باید یک سوکت ایجاد کنیم ( به مجموعه یک آدرس IP و یک پورت ، یک سوکت گفته میشود مثلا 127.0.0.1:5000 ) . به این طریق میتوان یک ارتباط Point to Point ایجاد کرد که توسط آن یک مسیر دو طرفه برای انتقال داده ها بین نود ها ایجاد میشود . لازمه ایجاد یک سوکت وجود یک Client و یک Server میباشد ( سرور سوکتی را پیشنهاد می دهد و Client از آن استفاده میکند) . بعد از موفقیت آمیز بودن مقدمات کار ، یک مسیر دو طرفه که کاملا مستقل از یکدیگر هستند برای ارتباط سرور و کلاینت ایجاد میشود . کاربران گاهی به این نکته توجه نمیکنند که واسط دریافت در Indy توسط TidTcpServer و TidTcpClient کاملا جدا از هم میباشد ، بنابراین برای ایجاد یک دیالوگ ( Dialog ) بین Client و Server که سرور شروع کننده آن است ، کمی مهارت لازم است .
هنگام مبادله اطلاعات باید به این نکته توجه کنیم که Tcp بر اساس data Stream کار میکند نه data Block . یعنی فریمها ارسال میشوند نه یک بلاک از اطلاعات . در ضمن ساختار Packet های ارسالی مخفی از دید کاربر است . مکانیزم های انتقالی هم در اینجا استفاده میشوند تا با الحاق داده ها با یکدیگر ، بسته های IP بزرگتری بسازند تا از Overhead مسیر بکاهند .
هنگامی که در Indy شما از توابع TidTcpClient.Writeln یا TidTcpClient.WriteBuffer برای فرستادن یک Block از داده ها استفاده میکنید ، نمیتوانید اطمینان داشته باشید که گیرنده دقیقا همان چیزی را دریافت میکند که شما فرستاده اید . شاید بلاکهای اضافه ای را نیز دریافت کند یا اینکه بلاکی را با یکسری اطلاعات اضافه تر دریافت کرده باشد . (چون در طی مسیر یکسری سرآیند ها به اطلاعاتی که شما فرستاده اید اضافه میشود . بحث در باره دلایل این کار خارج از موضوع کار ماست.)


UDP ? UDP !
برخلاف Tcp پروتکل Udp یک Block از داده ها را ارسال میکند . سایز این بلاک تا حداکثر 64 کیلو بایت میتواند باشد . اگر هنگام ارسال یک بلاک در این حالت ، قسمتی از بسته IP درست ارسال نشود کل بسته دور انداخته میشود و باید مجدد ارسال شود .
در هنگام استفاده از udp در Indy شما باید سایز بافر را در کامپوننت udp برابر با طول بزرگترین بلاکی که میخواهید ارسال کنید قرار دهید .
بر اساس تعریف استاندارد Udp ، برای ایجاد یک ارتباط بین دو نود چیزی شبیه سوکت وجود ندارد . هر کدام از انتقال بلاکها مقصد خاص خود را دارند . پس تعریف client و server با آنچه در Tcp دیدیم تفاوت دارد . یک سرور udp پورتی را ست میکند و تمام device های تحت شبکه از آن طریق میتوانند بلاکهای داده ی udp مورد نظرشان را به آن ارسال کنند . در اینجا فقط UdpSender و UdpReciver وجود دارد ولی Indy با تعریف TIdUDPClient و TIdUDPServer کمی مبهم عمل کرده است . هر دو این کامپوننتها میتوانند UdpBlock ها را بنویسند (Write ) اما همانطور که گفته شد تنها TIDUDPServer توانایی تعریف پورت را دارد . TIDUDPClient در قسمت Properties خود هم Host دارد و هم Port که این دو ، مقصد بلاکهای ارسالی توسط این client را مشخص میکنند و در طول اجرای برنامه قابل تغییر هستند .


با توجه به نحوه عملکرد الگوریتم انتقال UDP ، میتوانیم به راحتی یک UDP Broadcast را در شبکه داشته باشیم : پیغامی که برای تمام گیرنده هایی که در شبکه یک پورت باز دارند ارسال شود .


بر اساس ساختار اطلاعات ، UDP از محدوده اطلاعات در طی انتقال داده ها حفاظت میکند . به همین دلیل در TIDUDPServer یک event ای وجود دارد که توانایی دسترسی اختصاصی به هر یک از بلاکها را فراهم میکند . هر بلاک میتواند از یکی از Device های شبکه آمده باشد ، پس Event مذکور با استفاده از "binding " اطلاعات فرستنده ی بلاک را نگه می دارد .


پیشنهاد میکنم برای تکمیل و تفهیم این موضوع حتما به Chat application (http://delphi.about.com/library/weekly/aa101105a.htm)مراجعه کنید .

منابع :


http://www.parsstyle.com/instruction/view_points.php?id=2
http://delphi.about.com/od/adptips2005/qt/udpvstcp.htm




موفق باشید ...

seyed_farid
جمعه 31 شهریور 1385, 22:55 عصر
من میخوام سه کامپیوتر رو به هم شبکه کنم. دو تا بعنوان سرور و یکی بعنوان کلاینت. سرورها بصورت main و Standby باشند و برنامه کلاینت با هردوی آنها ارتباط داشته باشه. دوستان میتونند کمکی کنند در این زمینه؟
در این برنامه کار به این صورته که همیشه یکی از سرورها بعنوان سرور فعاله و دیگری بعنوان سرورStandby و کلاینت با سرور فعال تبادل اطلاعات میکنه و سرور St/by در صورتیکه اشکالی تو سرور اصلی پیش بیاد میاد تو مدار و حالا اون میشه سرور فعال و با کلاینت ارتباط برقرار میکنه. ارتباطشون هم از طریق پورت شبکه باید باشه. من برنامه ای دارم که روی سرورها نصب میشه و برنامه دیگری هم روی کامپیوتر کلاینت نصب میشه و سیستم اصلی و قطعات و مدارات سویچ روی سرورها نصب میشه و کلاینت در جای دیگری اطلاعات رو به سرور ارسال میکنه و سرور دستورات لازم رو به قطعات جانبی که از طریق پورت پرینتر متصل میشن میفرسته.
من با Tcpserver و Tcpclient کار رو شروع کردم . میخوام ببینم این کمپوننت جواب کارم رو میده یا از چیز دیگری استفاده کنم بهتره؟:متفکر:

Touska
شنبه 01 مهر 1385, 13:18 عصر
ای ول به شما به این کاری که شما می کنید در اصطلاح می گن Load Balancing که با ابزارهای Indy نیز میشه اینو پیاده کرد.

ببینید شما اگر Thread Connection ها خود را در حافظه نگه داشته باشید می توانید آنها را در یک memory Stream

ذخیره کرده و به سرور Standby خود بفرستید و آنجا انها را لود نمایید.

به شرطی که که دو سرور یک Address IP داشته و در یک پورت باز شده باشند و در مواقع اظطراری آن یکی به شبکه متصل شود.

در غیر اینصورت باید Connetion های خود را به اطلاع آن یکی برسانید که از دوباره از سمت سرور درخواست Connect داده شود.

موفق باشید :چشمک:

seyed_farid
یک شنبه 02 مهر 1385, 02:03 صبح
با تشکر از توسکای عزیز
دو کامپیوتر سرور باید همیشه در مدار باشند و همدیگر و کلاینت را چک کنند و به محض ایراد تو یکی دیگری وارد مدار بشه. این دو باید دو آدرس جدا داشته باشند تا بتونند با هم تبادل داشته باشند.
تو این مورد شما کاری کرده اید و آیا نمونه ای دارید یا نه؟

Touska
یک شنبه 02 مهر 1385, 19:00 عصر
با تشکر از توسکای عزیز
دو کامپیوتر سرور باید همیشه در مدار باشند و همدیگر و کلاینت را چک کنند و به محض ایراد تو یکی دیگری وارد مدار بشه. این دو باید دو آدرس جدا داشته باشند تا بتونند با هم تبادل داشته باشند.
تو این مورد شما کاری کرده اید و آیا نمونه ای دارید یا نه؟

به این شکل کار نکردم - ولی مقاله ای در رابطه به Application Server ها داشتم مثل Oracle

اگر پیدا کردم براتون می فرستم. (در مورد Load Balancing) :لبخند:

seyed_farid
دوشنبه 10 مهر 1385, 16:01 عصر
ممنونم که کمک میکنید. اگه بتونید زحمت بکشید برام بفرستید به ایمیلم.
من این برنامه رو شروع کردم . ببینید این چت چطوره؟

www2006
چهارشنبه 12 مهر 1385, 17:21 عصر
من این برنامه رو شروع کردم . ببینید این چت چطوره؟

چرا Port هات (بصورت پیش فرض) سه تا عدد متفاوت دارند ؟
کلا برای سرور و کل کلاینت ها در این مدل برنامه ها یک شماره ی منحصر بفرد و یکتا در نظر میگیرند .
(البته من از ایده ی شما خبر ندارم،اگر توضیح بدی ممنون میشم)

seyed_farid
یک شنبه 16 مهر 1385, 10:11 صبح
خدمت شما عرض کنم که این پورتها برای سرور در حقیقت پورتی هست که بگوش هست و برای کلاینت پورتی هست که میخواهد چیزی به آن پورت بفرستد و هر کسی روی پورت سرور چیزی بفرستد میگیرد و نیاز به کانکت شدن به سرور فعال هم ندارند و فقط موقع ارسال پیام گیرنده باید فعال باشد وگرنه خطا میدهد.

moeinelec
شنبه 09 دی 1385, 19:54 عصر
سلام به دوستان عزیز من این کد را وارد کردم
(IdCmdTCPServer1TIdCommandHandler1Command(ASender: TIdCommand
بعد بهم خطا میده
' Undeclared identifier: 'TIdCommand
فکر می کنم مشکل از namespace باشه کسی کمک مکنه؟ ممنون

vcldeveloper
یک شنبه 10 دی 1385, 08:58 صبح
بعد بهم خطا میده
' Undeclared identifier: 'TIdCommand

یونیت IdTCPServer را به لیست uses اضافه کنید.

moeinelec
یک شنبه 10 دی 1385, 19:17 عصر
اقای کشاورز اینها توی لیست uses هست ولی بازم error میده
IdComponent, IdTCPServer, IdExplicitTLSClientServerBase

barat121
شنبه 19 آبان 1386, 18:23 عصر
یعنی این تاپیک تموم شده و به نتیجه لازم هم رسیده ؟

spicirmkh
یک شنبه 02 دی 1386, 19:02 عصر
سلام

دوستان من می خواهم مرحله به مرحله indy در دلفی 2007 تست و اجرا کنم
که متاسفانه بعضی از کامپونت تغییر نام داده یا جابجا شدهاند از نظر مکانی یا دستوراتی که مدهم پیغام خطا میدهد مثل IdTcpClient1.Readln راهی وجود دارد بدون اینکه دلفی 7 نصب کنم در دلفی 2007 این دستورات اجرا کنم

با تشکر

attarizi
پنج شنبه 09 اسفند 1386, 12:01 عصر
بچه ها خدایی دمتون گرم انقدر چیز یاد گرفتم که دارم پس میوفتم

baby_tanhaa
سه شنبه 21 اسفند 1386, 10:16 صبح
حالا اگه بخوایم به جای string یه فایل بفرستیم مثلا یه عکس چیکار باید بکنیم ؟؟
میشه یکی توضیح بده؟؟

vcldeveloper
سه شنبه 21 اسفند 1386, 15:03 عصر
حالا اگه بخوایم به جای string یه فایل بفرستیم مثلا یه عکس چیکار باید بکنیم ؟
فایل رو در یک stream میریزید و با متد WriteStream آن را به سرور ارسال می کنید.

winer3549
دوشنبه 26 فروردین 1387, 15:54 عصر
سلام
میخواستم بدونم که میشه 4 یا 5 تا کلاینت هم داشت ؟؟؟

vcldeveloper
سه شنبه 27 فروردین 1387, 13:47 عصر
میخواستم بدونم که میشه 4 یا 5 تا کلاینت هم داشت ؟؟؟
در تعداد کلاینت محدودیتی وجود نداره، جز سخت افزار و توان شبکه موجود.

mms_4004
پنج شنبه 03 مرداد 1387, 20:32 عصر
سلام مرسی از مطالب مفیدتون دارم می خونم اما چون همیشه من عجولم می خواستم ببینم که با همین روش و استفاده از Indy میشه با استفاده از مودم و خط تلفن برنامه Client/Server رو اجرا کرد؟ اگر میشه کمی توضیح دهید. متشکر.

vcldeveloper
جمعه 04 مرداد 1387, 01:00 صبح
می خواستم ببینم که با همین روش و استفاده از Indy میشه با استفاده از مودم و خط تلفن برنامه Client/Server رو اجرا کرد؟
Indy نیاز به یک بستر شبکه داره. اگر با مودم و خط تلفنتان یک شبکه کامپیوتری بوجود آوردید (مثلا یک RAS Server درست کنید)، یا به یک شبکه کامپیوتری متصل شدید (مثل اتصال به اینترنت به شیوه Dial-up)، می تونید از indy برای اون کار استفاده کنید.

hedayat44
دوشنبه 28 دی 1388, 09:03 صبح
با تشكر
خواهشمند است ادامه دهيد.

ParsaNM
چهارشنبه 19 خرداد 1389, 10:25 صبح
ممنون دوستان ...
خيلي خوب و کامل بود ... خيلي استفاده کردم ...
خوب يک مشکل ايجاد شده ... ! در دلفي 2010 بعضي از property ها حذف شده و کلا اين کامپوننت ها منطقشون عوض شده ... مثلا براي اجراي TIDTCPServer مي بايست حتما onexecute نوشته شده یاشد (البته حتي خالي) شما در اين رابطه چيزي مي دونين ..؟

ایمان ناصری نیا
پنج شنبه 21 مرداد 1389, 02:09 صبح
با تشکر از راهنمایی های دوستان
دوستان اگه می تونستن اطلاعاتشونو بصورت مستند (pdf,word,...) در بیارن و هر کسی وظیفه تکمیل یه قسمتی به عهده میگرفت فکر میکنم نتیجه بهتری میگرفتیم