نمایش نتایج 1 تا 38 از 38

نام تاپیک: ساخت یک برنامه ی مسنجر تحت شبکه

  1. #1
    کاربر تازه وارد
    تاریخ عضویت
    بهمن 1386
    محل زندگی
    اصفهان
    سن
    33
    پست
    96

    Question چت چندکاربره و سرور

    من یک نمونه برنامه نوشتم که چت بین کلاینت و سرور هست که براساس شماره آی پی کار می کنه که میشه توش هم شماره کلاینت آی پی در اینترنت فرد رو داد و تحت اینترنت با هم دیگه چت کنند که من در این مورد دارم باهاش کار می کنم

    این برنامه وقتی کلاینت 1 دکمه Connect رو میزنه و به سرور اتصال پیدا می کنه مشکلی نداره ولی وقتی کلاینت 2 یا 3 یا هر چند تا دیگه دکمه Connect رو میزنن سرور به کلاینت آخری که دکمه Connect رو زده به اون می تونه فقط پیام ارسال کنه و دیگر کلاینت ها نمی تونه مشکل این برنامه کجاست

    نمونه ای از برنامه رو براتون می زارم لطف کنید و راهنمائیم کنید

    و از دلفی 7 استفاده می کنم و از ابزار Indy استفاده می کنم

    لطف کنید و مرا راهنمایی کنید
    فایل های ضمیمه فایل های ضمیمه

  2. #2
    کاربر دائمی آواتار nilidelphi
    تاریخ عضویت
    مرداد 1388
    محل زندگی
    ارومیه
    پست
    418

    Question ساخت یک برنامه ی مسنجر تحت شبکه

    با سلام خدمت دوستان
    من قرار یک برنامه ی تحت شبکه با دلفی بسازم که توش باید هم از socket استفاده کنم و هم از multithread استفاده کنم به این شکل :
    باید یک برنامه برای سرویس گیرنده بسازم که این چیزی نیست
    و یک برنامه برای سرویس دهنده بسازم که باید از یک ip و فقط از یک port استفاده کند یعنی به تعداد client هایی که به برنامه ی سرور کانکت می شوند از یک پورت باید به هر کدام یک ترد اختصاص بدهد.سوال اینجاست که برنامه ی طرف client چطوئ باید ip سرور رو بصورت پویا پیدا کنه و کانکت بشه؟
    و برنامه ی سرور چطور برای هر برنامه client که بهش کانکت میشه یک ترد اختصاص بده؟
    حالا اگه کسی بتونه کمک کنه خیلی ممنون می شم.

  3. #3
    کاربر دائمی آواتار nilidelphi
    تاریخ عضویت
    مرداد 1388
    محل زندگی
    ارومیه
    پست
    418

    Thumbs down نقل قول: چت چندکاربره و سرور

    دوست گرامی فکر کنم باید از multithreading استفاده کنی من خودم در حال تحقیقم اگه به نتیجه رسیدم برات میفرستم

  4. #4

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    برنامه ی طرف client چطوئ باید ip سرور رو بصورت پویا پیدا کنه و کانکت بشه؟
    برنامه های چت موجود (مثل یاهو مسنجر) آدرس سرور را بطور پویا پیدا نمی کنند، بلکه آدرس سرور ثابت هست، یا لیستی از آدرس های سرور دارند که اگر یکی کار نکرد، به سرور بعدی وصل میشند. البته در اینگونه برنامه های تجاری بجای IP Address از نام دامین استفاده می کنند، که اگر روزی IP Address تغییر کرد، نیاز نباشه کل کلاینت ها تغییر کنند، مثل آدرس وب سایت که همیشه برای کاربر استفاده کننده ثابت هست، حتی اگر IP سرور سایت تغییر کنه.

    و برنامه ی سرور چطور برای هر برنامه client که بهش کانکت میشه یک ترد اختصاص بده؟
    برنامه سرور یک پورت را باز میکنه، و یک Thread که اصطلاحا به آن Listener گفته میشه، را به آن اختصاص میده تا ترافیک پورت را تحت نظر داشته باشه. هر زمانی که کلاینت خاصی با سرور ارتباط برقرار میکنه، این Thread به سرور اطلاع میده، سرور هم یک Thread جدید میسازه، و پیام کلاینت را در اون Thread جدید پردازش میکنه.
    لزومی نداره شما درگیر اینگونه جزئیات بشید، این کارهای سطح پایین بطور خودکار توسط Indy مدیریت میشند


    وَ سَيَعْلَمُ الَّذِينَ ظَلَمُوا [آل محمد حقهم] أَيَّ مُنْقَلَبٍ يَنْقَلِبُونَ - الشعراء (227)
    و ظالمین [حق آل محمد (ص) ] به زودی خواهند دانست که به کدام بازگشتگاه بازخواهند گشت.

  5. #5
    کاربر تازه وارد
    تاریخ عضویت
    بهمن 1386
    محل زندگی
    اصفهان
    سن
    33
    پست
    96

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    آقای کشاورز سخن شما درست اما در یکی از تاپیک ها بود که با حلقه For پیام ارسال می کردید که به تمامی Client ها می رفت اما من نمی خوام اینطوری باشه بلکه سرور باید بدونه که کدوم Client درخواستی رو کرده که به همون Client پاسخ بده ولی کار شما برای همه می فرسته

  6. #6
    کاربر دائمی آواتار nilidelphi
    تاریخ عضویت
    مرداد 1388
    محل زندگی
    ارومیه
    پست
    418

    Question نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    سلام آقای کشاورز
    می تونید در مورد thread هایی که گفتین یهکم کاربردی تر توضیح بدین
    چون من باید یه همچین برنامه ای بنویسم که چند تا کلاینت از یک پورت به سرور متصل شوند(حالا ip خیلی مهم نیست)
    ولی من می خوام کلاینت ها از طریق سرور با هم چت کنند یا ......
    البته اگه در مورد پایگاه داده در Indy هم بتونین توضیح بدین ممنون میشم.

  7. #7

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    آقای کشاورز سخن شما درست اما در یکی از تاپیک ها بود که با حلقه For پیام ارسال می کردید که به تمامی Client ها می رفت اما من نمی خوام اینطوری باشه بلکه سرور باید بدونه که کدوم Client درخواستی رو کرده که به همون Client پاسخ بده ولی کار شما برای همه می فرسته
    برای چه کاری بود؟ قرار نیست هر کدی هر جا کاربرد داشته باشه. یکی میخواد از طرف سرور یک پیامی را برای همه کلاینت هایی که به اون سرور لاگین کردند، ارسال کنه. یکی میخواد هر زمان که کلاینت درخواستی به سرور ارسال کرد، سرور جوابش را بده.
    اونی که شما دیدید، برای ارسال پیام از سرور به همه کلاینت ها، بدون آنکه کلاینتی درخواستی ارسال کرده باشه، بود. مثلا سرور میخواد به همه کلاینت های خودش بگه که باید لیست خودشان را آپدیت کنند.
    وقتی یک کلاینت برای سرور درخواستی ارسال میکنه، سرور بطور خودکار برای آن درخواست یک Thread اختصاصی درست میکنه، و جوابی که سرور به اون کلاینت میده، از طریق همون Thread هست و تداخلی با سایر Threadها نداره.

    می تونید در مورد thread هایی که گفتین یهکم کاربردی تر توضیح بدین
    چون من باید یه همچین برنامه ای بنویسم که چند تا کلاینت از یک پورت به سرور متصل شوند(حالا ip خیلی مهم نیست)
    ولی من می خوام کلاینت ها از طریق سرور با هم چت کنند یا ......
    همانطور که گفتم، نیازی نیست شما درگیر اون جزئییاتی که گفتم بشید. Indy خودش اون بخش از کار را برای شما انجام میده. کاری که شما باید انجام بدید، مواردی هست مثل چگونکی لاگین کردن کلاینت ها به سرور، قالب پیام های رد و بدل شده بین سرور و کلاینت، مدیریت کلاینت ها در سمت سرور، و مواردی از این قبیل.

    البته اگه در مورد پایگاه داده در Indy هم بتونین توضیح بدین ممنون میشم.
    Indy ربطی به پایگاه داده نداره. Indy ابزاری برای انتقال داده بر روی شبکه با استفاده از Protocolهای شناخته شده ایی مثل TCP, HTTP, FTP, POP3، و غیره. اینکه داده تبادل شده رکورد بانک اطلاعاتی هست، یا یک فایل هست، یا یک پیام ساده متنی، ربطی به Indy نداره. شما می تونید از Indy به عنوان زیرساخت استفاده کنید، و بر روی آن لایه ایی برای کار با بانک اطلاعاتی بسازید که برای تبادل داده با سایر لایه ها، از Indy استفاده میکنه. در هر حال، این بحث ربطی به موضوع این تاپیک نداره. اگر مایلید نمونه برنامه ایی ببینید که داده های بانک اطلاعاتی را از طریق Indy در شبکه منتقل میکنه، یک نمونه ساده به همراه مثال های Mastering Delphi 7 هست.


    وَ سَيَعْلَمُ الَّذِينَ ظَلَمُوا [آل محمد حقهم] أَيَّ مُنْقَلَبٍ يَنْقَلِبُونَ - الشعراء (227)
    و ظالمین [حق آل محمد (ص) ] به زودی خواهند دانست که به کدام بازگشتگاه بازخواهند گشت.

  8. #8
    کاربر تازه وارد
    تاریخ عضویت
    بهمن 1386
    محل زندگی
    اصفهان
    سن
    33
    پست
    96

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    ببینید آقای کشاورز من طبق گفته خودتون اومدم و لیست کاربرانی که اتصال می کنن رو داخل یک آرایه میریزم اما Server وقتی که می خواد پیام ارسال کنه به آخرین کاربری که Connect شده پیام رو ارسال می کنه

    میشه بگید چطوری بفهمم کدوم کاربره و چطوری براش ارسال کنم

  9. #9

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    ببینید آقای کشاورز من طبق گفته خودتون اومدم و لیست کاربرانی که اتصال می کنن رو داخل یک آرایه میریزم اما Server وقتی که می خواد پیام ارسال کنه به آخرین کاربری که Connect شده پیام رو ارسال می کنه

    میشه بگید چطوری بفهمم کدوم کاربره و چطوری براش ارسال کنم
    من که کد شما را برای ذخیره IP کاربران، و چگونگی ارسال پیام ندیدم. وقتی ندیدم، چی رو راهنمایی کنم؟


    وَ سَيَعْلَمُ الَّذِينَ ظَلَمُوا [آل محمد حقهم] أَيَّ مُنْقَلَبٍ يَنْقَلِبُونَ - الشعراء (227)
    و ظالمین [حق آل محمد (ص) ] به زودی خواهند دانست که به کدام بازگشتگاه بازخواهند گشت.

  10. #10
    کاربر تازه وارد
    تاریخ عضویت
    بهمن 1386
    محل زندگی
    اصفهان
    سن
    33
    پست
    96

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    این هم کد من خدمت شما


    private
    FSyncObj : TMultiReadExclusiveWriteSynchronizer;
    FClients : TObjectList;
    public
    property Clients: TObjectList read FClients;

    end;
    var
    Form1: TForm1;
    mythread : TIdPeerThread ;
    implementation

    {$R *.dfm}
    procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
    begin
    FSyncObj.BeginWrite;
    try
    FClients.Add(AThread);
    finally
    FSyncObj.EndWrite;
    end;
    end;
    procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
    begin
    CDarkhast.Items.Add(AThread.Connection.ReadLn()) ;
    end;
    procedure TForm1.FormCreate(Sender: TObject);
    begin
    FSyncObj := TMultiReadExclusiveWriteSynchronizer.Create;
    FClients := TObjectList.Create(False);
    end;
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
    FreeAndNil(FClients);
    FreeAndNil(FSyncObj);
    end;
    procedure TForm1.IdTCPServer1Disconnect(AThread: TIdPeerThread);
    begin
    FSyncObj.BeginWrite;
    try
    FClients.Remove(AThread);
    finally
    FSyncObj.EndWrite;
    end;
    end;


    و این هم برای ارسال پیام


    FSyncObj.BeginRead;
    try
    for i := 0 to FClients.Count-1 do
    begin
    Client := FClients[i] as TIdPeerThread;
    Client.Connection.WriteLn(Server);
    end;
    finally
    FSyncObj.EndRead;
    end;

  11. #11

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    خب، بررسی کردید که هر زمان که کلاینتی به سرور متصل میشه، آیا Thread مربوط به آن به درستی در لیست قرار میگیره یا نه؟
    کلاینت های شما چطوری به سرور وصل میشند؟ بعد از هر درخواست بلافاصله disconnect میشند؟

    مقدار Server در کد زیر چی هست؟
    Client.Connection.WriteLn(Server);


    وَ سَيَعْلَمُ الَّذِينَ ظَلَمُوا [آل محمد حقهم] أَيَّ مُنْقَلَبٍ يَنْقَلِبُونَ - الشعراء (227)
    و ظالمین [حق آل محمد (ص) ] به زودی خواهند دانست که به کدام بازگشتگاه بازخواهند گشت.

  12. #12
    کاربر تازه وارد
    تاریخ عضویت
    بهمن 1386
    محل زندگی
    اصفهان
    سن
    33
    پست
    96

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    متن هستش

    Server یک متغییر از نوع string هست

  13. #13
    کاربر تازه وارد
    تاریخ عضویت
    بهمن 1386
    محل زندگی
    اصفهان
    سن
    33
    پست
    96

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    نه کلاینت ها وقتی متصل می شند disconnect نمیشن و همیشه وصل هستند

  14. #14

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    تشکر از کد شما ولی اگر توضیح هم برا من بدهید ممنون می شوم چون باید کنفرانس بدهم لطفا درخواستم را پاسخ دهید

  15. #15

    Arrow نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    نقل قول نوشته شده توسط فریده صادقی مشاهده تاپیک
    تشکر از کد شما ولی اگر توضیح هم برا من بدهید ممنون می شوم چون باید کنفرانس بدهم لطفا درخواستم را پاسخ دهید
    میشه در مورد درخاستتون بیشتر توضیح بدید.


  16. #16

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    یکی میخواد از طرف سرور یک پیامی را برای همه کلاینت هایی که به اون سرور لاگین کردند، ارسال کنه.
    جناب کشاورز میشه چگونگی انجام این کار رو شرح بدید ؟
    با این روش میشه تعداد اتصالات رو بدست آورد . اما چگونگی ارسال پیام برای تک تک کلاینت ها رو نمیدونم .
    i := TCPServer.Bindings.Count;


    ضمناً یه سوال داشتم : در شرایطی که مثلاً به دلیل مشکلات Listen ، امکان استفاده از TCPServer در کلاینت ها وجود نداشه باشه استفاده از Timer برای دریافت پیام های سرور در طولانی مدت میتونه قابل اطمینان باشه ؟ امکان پیاده سازی رویدادی در این مورد وجود نداره ؟
    آخرین ویرایش به وسیله مهران رسا : شنبه 01 خرداد 1389 در 15:36 عصر

  17. #17

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    نقل قول نوشته شده توسط M8SPY مشاهده تاپیک
    جناب کشاورز میشه چگونگی انجام این کار رو شرح بدید ؟
    با این روش میشه تعداد اتصالات رو بدست آورد . اما چگونگی ارسال پیام برای تک تک کلاینت ها رو نمیدونم .
    i := TCPServer.Bindings.Count;


    ضمناً یه سوال داشتم : در شرایطی که مثلاً به دلیل مشکلات Listen ، امکان استفاده از TCPServer در کلاینت ها وجود نداشه باشه استفاده از Timer برای دریافت پیام های سرور در طولانی مدت میتونه قابل اطمینان باشه ؟ امکان پیاده سازی رویدادی در این مورد وجود نداره ؟
    کجای کار مشکل دارید ؟
    به شکل زیر میتونید به IP سیستم های متصل شده به سرور دسترسی پیدا کنید :
    IdTCPServer1.Bindings.Items[i].

    متد هایی برای ارسال و دریافت و ... در اختیار شما قرار میگیره که میتونید تو یک حلقه پیغامتون رو برای همه اعضای لیست بفرستید ، برای جلوگیری از وقفه در طول ارسال هم قبل از ارسال آنلاین بودن سیستم مقصد رو بررسی کنید .

    برای تست کردن آنلاین بودن سیستم هم میتونید IP سیستم رو پینگ کنید ( قبلا نمونه ای قرار داده بودم )

  18. #18

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    متد هایی برای ارسال و دریافت و ... در اختیار شما قرار میگیره که میتونید تو یک حلقه پیغامتون رو برای همه اعضای لیست بفرستید ، برای جلوگیری از وقفه در طول ارسل هم قبل از ارسال آنلاین بودن سیستم مقصد رو بررسی کنید .

    برای تست کردن آنلاین بودن سیستم هم میتونید IP سیستم رو پینگ کنید ( قبلا نمونه ای قرار داده بودم )
    مرسی برادر مجتبی . همون متد ارسال رو نمیدونم . ممنون میشم راهنمایی کنی.
    ضمناً راه بهتری برای بررسی برقرار بودن ارتباط از طریق خود Indy وجود نداره ؟ Ping زمان بر هست .

  19. #19

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    مرسی برادر مجتبی . همون متد ارسال رو نمیدونم . ممنون میشم راهنمایی کنی.
    با کد زیر میتونید IP سیستم ها رو تو یک حلقه بگیرید ، برای ارسال هم باید از یک TCPClient در سمت سرور استفاده کنید و سیستم های کلاینت باید TCPServer داشته باشند ، قبلا هم آقای کشاورز در یکی از پست هاشون اشاره کردن کار TCPServer گوش دادن به درخواست و کار TCPClient ارسال درخواست هست .
    IdTCPServer1.Bindings.Items[SystemIndex].PeerIP;


    ضمناً راه بهتری برای بررسی برقرار بودن ارتباط از طریق خود Indy وجود نداره ؟ Ping زمان بر هست .
    استفاده از Icmp سرعت خوبی هم داره :
    IcmpClient.Host:= '127.0.0.1';
    IcmpClient.Ping();
    if IcmpClient.ReplyStatus.BytesReceived=0 then
    ShowMessage('False')
    else
    ShowMessage('True');

  20. #20

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    سیستم های کلاینت باید TCPServer داشته باشند
    مسئله همینجاست . سیستم کلاینت اگه TCPServer داشته باشه که دیگه بهش کلاینت نمیگن . همونطور که گفتم امکان استفاده از TCPServer در کلاینت ها به هیچ وجه وجود نداره . چراکه مشکلاتی مثل فایروال ، پورت های اشغال شده و ... در رایانه کاربران از دست ما خارج هست . پس مسئله Listening از سمت کلاینت منتفی هست .
    اما الآن سوال اینجاست که آیا متد خاصی برای اینکار وجود نداره ؟ اصلاً وظیفه شی Bindings چیه ؟ اگه بخوام منظورم رو واضح تر بگم . من میخوام یک سیستم چت ساده ایجاد کنم . بطوری که پیام های شما برای رسیدن به مقصد ابتدا باید از سرور عبور کنن . خب سرور پیغام کنترلی رو دریافت میکنه و با نشانه ای که در پیغام هست تصمیم میگیره متن مورد نظر رو برای کلاینت شماره 2 ارسال کنه . پیغام ها در سرور در رویداد Execute دریافت میشن و جواب هم از همین طریق ارسال میشه . اما اینبار نمیخوایم جواب رو برای کاربر کانشکن جاری ارسال کنیم . میخوایم بعد از پردازش های انجام و مشخص شدن Index کانشکن مورد نظر ، جواب رو برای کاربر دیگه ای ارسال کنیم .

  21. #21

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    حالا ما هر چی میگیم بگو مشکل پیش میاد ، بابا راه اصولیش همینه ، شما 2 تا پرت برای برنامت نیاز داری ، در ضمن میتونی برنامت رو به فایروال معرفی کنی که نیازی به گرفتن اجازه از کاربر نباشه .

    ضمناً یه سوال داشتم : در شرایطی که مثلاً به دلیل مشکلات Listen ، امکان استفاده از TCPServer در کلاینت ها وجود نداشه باشه استفاده از Timer برای دریافت پیام های سرور در طولانی مدت میتونه قابل اطمینان باشه ؟
    شئ تایمر از پیغام WM_Timer استفاده میکنه ، پس نمیشه بهش اطمینان داشت ممکنه پیغام در صف پردازش بمونه و برای پردازشش زمان طولانی وقت صرف بشه .

    ابته باید تجربه دیگر دوستان رو هم در نظر گرفت ، شاید کسی ایده یا راه حلی داشته باشه .

  22. #22

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    حالا ما هر چی میگیم بگو مشکل پیش میاد ، بابا راه اصولیش همینه ، شما 2 تا پرت برای برنامت نیاز داری ، در ضمن میتونی برنامت رو به فایروال معرفی کنی که نیازی به گرفتن اجازه از کاربر نباشه .
    امکان استفاده از راهی که شما میگی وجود نداره . قبلاً در روش Non-Blocking با استفاده از رویداد ها خیلی راحت این مسائل رو حل میکردم .

    سیستم های کلاینت باید TCPServer داشته باشند
    مسئله همینجاست . سیستم کلاینت اگه TCPServer داشته باشه که دیگه بهش کلاینت نمیگن . همونطور که گفتم امکان استفاده از TCPServer در کلاینت ها به هیچ وجه وجود نداره . چراکه مشکلاتی مثل فایروال ، پورت های اشغال شده و ... در رایانه کاربران از دست ما خارج هست . پس مسئله Listening از سمت کلاینت منتفی هست .
    اما الآن سوال اینجاست که آیا متد خاصی برای اینکار وجود نداره ؟ اصلاً وظیفه شی Bindings چیه ؟ اگه بخوام منظورم رو واضح تر بگم . من میخوام یک سیستم چت ساده ایجاد کنم . بطوری که پیام های شما برای رسیدن به مقصد ابتدا باید از سرور عبور کنن . خب سرور پیغام کنترلی رو دریافت میکنه و با نشانه ای که در پیغام هست تصمیم میگیره متن مورد نظر رو برای کلاینت شماره 2 ارسال کنه . پیغام ها در سرور در رویداد Execute دریافت میشن و جواب هم از همین طریق ارسال میشه . اما اینبار نمیخوایم جواب رو برای کاربر کانشکن جاری ارسال کنیم . میخوایم بعد از پردازش های انجام و مشخص شدن Index کانشکن مورد نظر ، جواب رو برای کاربر دیگه ای ارسال کنیم .
    احتمالاً آقای کشاورز بتونن راه حلی ارائه کنند

  23. #23

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    همونطور که گفتم امکان استفاده از TCPServer در کلاینت ها به هیچ وجه وجود نداره . چراکه مشکلاتی مثل فایروال ، پورت های اشغال شده و ... در رایانه کاربران از دست ما خارج هست . پس مسئله Listening از سمت کلاینت منتفی هست .
    سایر برنامه های چت معروف هم همچین مکانیزمی را پیاده سازی می کنند. بحث فایروال و پورت اشغال شده هم در هر صورت برای یک برنامه تحت شبکه هست. اگر برنامه شما فقط کلاینت هم باشه، وقتی میخواد پیامی به سرور ارسال کنه، فایروال جلوش رو میگیره، و پورت مورد استفاده اش هم ممکنه اشغال شده باشه. پس فرقی از این بابت نمیکنه. شما اگر میخواید پیامی از دیگران دریافت کنید، باید جایی روی یک پورت Listening کنید، و منتظر پیام باشید. یک کامپوننت سرور این امکان رو به طور خودکار بهتون میده.

    قبلاً در روش Non-Blocking با استفاده از رویداد ها خیلی راحت این مسائل رو حل میکردم .
    در اون حالت هم عملا شما در حال Listen کردن روی یک پورت بودید. هر زمان داده ایی به اون پورت می رسید، یک Event در برنامه شما فراخوانی میشد، و شما پردازش خودتان را انجام می دادید.

    اصلاً وظیفه شی Bindings چیه ؟
    خصوصیت Bindings ربطی به این بحث نداره. این خصوصیت زمانی استفاده میشه که یک سرور بخواد روی چند پورت مختلف Listen کنه، یا چند کارت شبکه روی یک سیستم وجود داشته باشه، و سرور بخواد از یکی از این کارت ها استفاده کنه، یا روی هر کارت شبکه موجود یک Socket باز کنه، و روی پورت تعیین شده Listen کنه. در واقع با استفاده از Bindings شما IP و Portایی که سرور باید روی آن Listen کنه را مشخص می کنید.

    من میخوام یک سیستم چت ساده ایجاد کنم . بطوری که پیام های شما برای رسیدن به مقصد ابتدا باید از سرور عبور کنن . خب سرور پیغام کنترلی رو دریافت میکنه و با نشانه ای که در پیغام هست تصمیم میگیره متن مورد نظر رو برای کلاینت شماره 2 ارسال کنه .
    از یک IdCmdTcpServer استفاده کنید. برای آن فرامین مثل Login, LogOut, SendMsg، و غیره تعریف کنید. هر زمان که کلاینتی به سرور متصل شد، و فرمان Login را ارسال کرد، مشخصات اتصالش را چک کنید، اگر صحیح بود، ارتباط را قبول کنید، و آدرس IP و Port آن کلاینت را به همراه شناسه آن در یک لیست در سرور ذخیره کنید. اگر صحیح نبود، اتصالش را قطع کنید.
    هر زمان هم کلاینتی دستور LogOut را صادر کرد، شناسه اش را از لیستی که در سرور دارید، پیدا کنید، و آن کلاینت را از لیست کاربران خارج کنید.
    هر زمان کلاینتی دستور SendMsg را به سرور صادر کرد، شناسه کاربر مقصد را از پیام دریافتی استخراج کنید، و نام وی را در لیست کاربران متصل به سرور جستجو کنید. اگر شناسه اش جزو لیست کاربران متصل به سرور بود، آدرس IP و Portاش را از همان لیست استخراج کنید، و پیام مربوطه را به آن آدرس IP و Port ارسال کنید.


    وَ سَيَعْلَمُ الَّذِينَ ظَلَمُوا [آل محمد حقهم] أَيَّ مُنْقَلَبٍ يَنْقَلِبُونَ - الشعراء (227)
    و ظالمین [حق آل محمد (ص) ] به زودی خواهند دانست که به کدام بازگشتگاه بازخواهند گشت.

  24. #24

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    در اون حالت هم عملا شما در حال Listen کردن روی یک پورت بودید. هر زمان داده ایی به اون پورت می رسید، یک Event در برنامه شما فراخوانی میشد، و شما پردازش خودتان را انجام می دادید.
    در اون حالت پیام ها از طریق مسیر کانکشنی که از قبل باز شده بود ارسال میشد و نیازی به ایجاد اتصال جدید و متعاقباً به وجود آمدن پورت اضافه ای در کلاینت ها نبود .
    آدرس IP و Portاش را از همان لیست استخراج کنید، و پیام مربوطه را به آن آدرس IP و Port ارسال کنید.
    و دیگه نیاز به این کار نبود .
    هر زمان هم کلاینتی دستور LogOut را صادر کرد، شناسه اش را از لیستی که در سرور دارید، پیدا کنید، و آن کلاینت را از لیست کاربران خارج کنید.
    آمدیم و کلاینت هیچ وقت فرمان Logout ارسال نکرد . با قطع اتصال اینترنت کلاینت ، Connection مربوطه چطوری میخواد از این موضوع با خبر بشه ؟ احتمالاً با پینگ ؟؟! حداقل باید توسط رویدادی در سرور مشخص بشه کدوم کلاینت قطع شده . این رویداد ها در non-blocking وجود دارند . امکان پیاده سازیشون برای Indy وجود نداره ؟
    بحث فایروال و پورت اشغال شده هم در هر صورت برای یک برنامه تحت شبکه هست
    اما هموطنور که میدونید در سیستم عاملی مثل ویستا فایروال فقط زمانی که برنامه بخواد Listen بشه از کاربر مجوز درخواست میکنه و در حالت اتصال به سرور ممنوعیتی اعمال نمیشه

    سایر برنامه های چت معروف هم همچین مکانیزمی را پیاده سازی می کنند
    منظور برنامه هایی هست که بر پایه ی Blocking نوشته شدند ؟
    آخرین ویرایش به وسیله مهران رسا : شنبه 01 خرداد 1389 در 19:01 عصر

  25. #25

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    در اون حالت پیام ها از طریق مسیر کانکشنی که از قبل باز شده بود ارسال میشد و نیازی به ایجاد اتصال جدید و متعاقباً به وجود آمدن پورت اضافه ای در کلاینت ها نبود .
    الان هم می تونید با همون Indy اون کار رو انجام بدید، با این تفاوت که باید خودتون یک Thread جداگانه ایجاد کنید، و در اون خودتون چک کردن سوکت رو برعهده بگیرید.
    البته اجباری هم به استفاده از Indy نیست، دوست داشتید، می تونید از ICS استفاده کنید که Asynchronous هست، یا مستقیما از WinSock استفاده کنید.

    و دیگه نیاز به این کار نبود .
    چرا نبود؟! دریافت لیست IP و Port مربوط به سرور چت شما ست، و ربطی به کلاینت ها نداره. شما در هر حال باید در سمت سرور لیستی از کلاینت های متصل شده نگهداری کنید.

    آمدیم و کلاینت هیچ وقت فرمان Logout ارسال نکرد . با قطع اتصال اینترنت کلاینت ، Connection مربوطه چطوری میخواد از این موضوع با خبر بشه ؟ احتمالاً با پینگ ؟؟! حداقل باید توسط رویدادی در سرور مشخص بشه کدوم کلاینت قطع شده . این رویداد ها در non-blocking وجود دارند . امکان پیاده سازیشون برای Indy وجود نداره ؟
    هیچ راه حل تضمین شده ایی برای فهمیدن قطع اتصال ناگهانی طرف مقابل وجود نداره. همه برنامه های چت معروفی که می شناسید، برای این منظور در فواصل زمانی معین بسته ایی بین سرور و کلاینت ارسال میشه، تا دو طرف از وجود اتصال مطمئن بشند.

    منظور برنامه هایی هست که بر پایه ی Blocking نوشته شدند ؟
    نه؛ برنامه های معروفی مثل همین یاهو مسنجر.


    وَ سَيَعْلَمُ الَّذِينَ ظَلَمُوا [آل محمد حقهم] أَيَّ مُنْقَلَبٍ يَنْقَلِبُونَ - الشعراء (227)
    و ظالمین [حق آل محمد (ص) ] به زودی خواهند دانست که به کدام بازگشتگاه بازخواهند گشت.

  26. #26

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    شما در هر حال باید در سمت سرور لیستی از کلاینت های متصل شده نگهداری کنید.
    بله . اما با روشی که عرض کردم نیازی به درگیر شدن با IP و پورت نیست . همون نگهداری Index کانکشن مربوط به کاربر لاگین شده کافی هست . همچنین در این روش عمر آنلاین بودن کاربران به اتصال کانکشن اولیه بستگی داره . یعنی کانکشنی که از زمان Login ایجاد میشه تا زمان Logout ، ضمن تعیین وضعیت آنلاین بودن ، تا پایان اتصال به عنوان یک بستر ارتباطی ، فعال باقی میمونه.

    نه؛ برنامه های معروفی مثل همین یاهو مسنجر.
    جناب کشاورز از مشکلات فایروال و ... هم که چشم پوشی کنیم در روشی که کلاینت ها باید Listen بمونن امنیت پایین هست . خرابکاران به سرور دسترسی ندارند. در مقابل دسترسی به کلاینت ها و ایجاد تغییرات خرابکارانه کار سختی نیست.

    یا مستقیما از WinSock استفاده کنید.
    در دلفی چطوری میشه از Winsock استفاده کرد ؟ امکان داره منابع آموزشی در این مورد معرفی کنید ؟
    خیلی ممنون .

  27. #27

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    در دلفی چطوری میشه از Winsock استفاده کرد ؟ امکان داره منابع آموزشی در این مورد معرفی کنید ؟
    یک نمونه : http://www.coderprofile.com/networks...insock-example

  28. #28

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    همچنین در این روش عمر آنلاین بودن کاربران به اتصال کانکشن اولیه بستگی داره . یعنی کانکشنی که از زمان Login ایجاد میشه تا زمان Logout ، ضمن تعیین وضعیت آنلاین بودن ، تا پایان اتصال به عنوان یک بستر ارتباطی ، فعال باقی میمونه.
    در Indy هم Connection شما تا زمانی که کلاینت Disconnect نکنه، همچنان باقی میمانه. حتی میشه در هنگام اتصال کلاینت، شی Thread اختصاص داده شده به آن در سمت سرور را گرفت، و هر بار لازم بود، از طریق آن با کلاینت مربوطه ارتباط برقرار کرد، اما در این صورت، داده ها در سمت کلاینت به IdTcpClient که ارتباط با سرور را برقرار کرده، ارسال میشند.

    در دلفی چطوری میشه از Winsock استفاده کرد ؟
    به همون صورتی که در ++Visual C از توابع API ویندوز استفاده میشه؛ یونیت مربوطه را به لیست uses اضافه می کنید، و توابع مربوطه را فراخوانی می کنید. برای راهنمای درباره کار با این توابع هم می تونید به MSDN مراجعه کنید.

    البته یک کتاب با عنوان The Tomes of Delphi: Basic 32-Bit Communications Programming از انتشارات Wordware هم وجود داره که به برنامه نویسی سوکت با استفاده از WinSock و TAPI در دلفی می پردازه.


    جناب کشاورز از مشکلات فایروال و ... هم که چشم پوشی کنیم در روشی که کلاینت ها باید Listen بمونن امنیت پایین هست . خرابکاران به سرور دسترسی ندارند. در مقابل دسترسی به کلاینت ها و ایجاد تغییرات خرابکارانه کار سختی نیست.
    نه، از نظر امنیت تفاوتی ندارند. تصور نکنید Indy برای خودش یک سری کارهایی انجام میده، Indy هم در واقع در لایه های زیرین خودش از WinSock روی ویندوز برای تبادل داده استفاده میکنه.


    وَ سَيَعْلَمُ الَّذِينَ ظَلَمُوا [آل محمد حقهم] أَيَّ مُنْقَلَبٍ يَنْقَلِبُونَ - الشعراء (227)
    و ظالمین [حق آل محمد (ص) ] به زودی خواهند دانست که به کدام بازگشتگاه بازخواهند گشت.

  29. #29

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    جناب کشاورز از اینکه به سوالات من پاسخ میدید متشکرم .
    اما در این صورت، داده ها در سمت کلاینت به IdTcpClient که ارتباط با سرور را برقرار کرده، ارسال میشند.
    در اونجا میشه رویدادی مثل DataArivall پیاده سازی کرد ؟
    ستفاده از Timer برای دریافت پیام های سرور در طولانی مدت میتونه قابل اطمینان باشه ؟

  30. #30

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    در اونجا میشه رویدادی مثل DataArivall پیاده سازی کرد ؟
    خودش همچین چیزی نداره؛ باید کدهاش رو بررسی کرد، و دید که آیا میشه یک کلاس جدید از اون، یا از کلاس های والدش مشتق کرد که این امکان رو داشته باشه، یا نه. من بررسی نکردم.


    وَ سَيَعْلَمُ الَّذِينَ ظَلَمُوا [آل محمد حقهم] أَيَّ مُنْقَلَبٍ يَنْقَلِبُونَ - الشعراء (227)
    و ظالمین [حق آل محمد (ص) ] به زودی خواهند دانست که به کدام بازگشتگاه بازخواهند گشت.

  31. #31

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    حتی میشه در هنگام اتصال کلاینت، شی Thread اختصاص داده شده به آن در سمت سرور را گرفت، و هر بار لازم بود، از طریق آن با کلاینت مربوطه ارتباط برقرار کرد
    اینکار چطور امکان پذیر هست ؟
    راستش اصلاً حوصله درگیر شدن با پیچیدگی Winsock رو ندارم . اگه مورد بالا حل بشه در سمت کلاینت هم میشه ترفندهایی به کار برد.

    در کل با توجه به مکانیزم Blocking ، میشه پروسه ارسال و دریافت Pm رو به گونه ای طراحی کرد که هر کاربر دارای یک صندوق پیام باشه و در یک بازه زمانی مشخص به صورت مداوم برای چک کردن صندوق ورودی خودش به سرور درخواست ارسال کنه و ادامه ماجرا...

  32. #32

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    اینکار چطور امکان پذیر هست ؟
    از طریق پارامتری که رویداد OnExecute سرور بهتون میده.

    راستش اصلاً حوصله درگیر شدن با پیچیدگی Winsock رو ندارم .
    مجبور نیستید که مستقیما با WinSock کار کنید، می تونید از ICS استفاده کنید که Non-blocking هست، و رابط ساده تری هم نسبت به WinSock داره.


    وَ سَيَعْلَمُ الَّذِينَ ظَلَمُوا [آل محمد حقهم] أَيَّ مُنْقَلَبٍ يَنْقَلِبُونَ - الشعراء (227)
    و ظالمین [حق آل محمد (ص) ] به زودی خواهند دانست که به کدام بازگشتگاه بازخواهند گشت.

  33. #33

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    از طریق پارامتری که رویداد OnExecute سرور بهتون میده.
    من همچین برداشتی داشتم :

    implementation

    var
    Connections: array [1 .. 100000] of TIdContext;
    i: integer;

    procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
    begin
    i := i + 1;
    Connections[i] := AContext;
    end;


    آیا این راه صحیحه ؟

  34. #34

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    آیا این راه صحیحه ؟
    بله، این IdContext تا زمانی که کاربر Disconnect نشه، معتبر هست؛ البته لزومی نداره از یک آرایه استفاده کنید، بلکه بهتره از یک لیست Generic استفاده کنید:

    interface
    uses
    Forms, Generics.Collections;

    type

    TForm1 = class(TForm)
    ...
    private
    Connections : TList<TIdContext>;
    public

    end;

    implementation

    procedure TForm1.FormCreate(Sender: TObject);
    begin
    Connections := TList<TIdContext>.Create;
    end;

    procedure TForm1.FormDestroy(Sender: TObject);
    begin
    Connections.Free;
    end;

    procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
    begin
    Connections.Add(AContext);
    end;


    وَ سَيَعْلَمُ الَّذِينَ ظَلَمُوا [آل محمد حقهم] أَيَّ مُنْقَلَبٍ يَنْقَلِبُونَ - الشعراء (227)
    و ظالمین [حق آل محمد (ص) ] به زودی خواهند دانست که به کدام بازگشتگاه بازخواهند گشت.

  35. #35

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    آقای کشاورز اگه بخوایم پروسه بالا رو برای عملیات Login شرح بدیم به این صورت خواهد بود :

    • کلاینت Username و Password را برای سرور ارسال میکند.
    • سرور در رویداد Onexecute بعد از بررسی صحت نام کاربری و کلمه عبور و با توجه به AContext دریافت شده یک عضو به اعضای Connections اضافه میکند.
    • در صورت اتصال موفقیت آمیز ، پیغام های بعدی که از سمت کلاینت ارسال میشوند نیازی به نام کاربری و کلمه عبور ندارند و تشخیص Valid بودن کلاینت از طریق همان اعضای موجود در Connections صورت میگیرد .
    • کلاینت یک پیغام متنی برای سرور ارسال میکند .
    • سرور در رویداد OnExecute ـ ، AContext فعلی را با تمامی اعضای Connections بررسی کرده و در صورت یافتن آن در لیست ، اجازه میدهد ادامه عملیات انجام شود .

    اما سوال اینجاست که آیا روش فوق بهترین راهی هست که میشه برای مدیریت Connection ها بکار برد ؟ ضمن اینکه ممکنه تعداد اتصالات بسیار زیاد باشن و با هر پیغامی که از طرف Client ها ارسال میشه باید برای مطمئن شدن از Valid بودن Connection جاری ، اون رو با کل Connection های ایجاد شده از قبل ، بررسی کنیم .
    آخرین ویرایش به وسیله مهران رسا : جمعه 11 تیر 1389 در 11:18 صبح

  36. #36

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    اما سوال اینجاست که آیا روش فوق بهترین راهی هست که میشه برای مدیریت Connection ها بکار برد ؟ ضمن اینکه ممکنه تعداد اتصالات بسیار زیاد باشن و با هر پیغامی که از طرف Client ها ارسال میشه باید برای مطمئن شدن از Valid بودن Connection جاری ، اون رو با کل Connection های ایجاد شده از قبل ، بررسی کنیم .
    در صورت پیاده سازی صحیح لیست، مشکلی بوجود نمیاد. مثلا سرور میتونه برای جستجوی سریع از یک Hash Table مناسب استفاده کنه. در ضمن، اینکه کاربر یک بار لاگین کنه، و بعدش هر پیامی خواست ارسال کنه، درست نیست؛ بلکه کاربر میتونه یک بار لاگین کنه، و سپس در صورت موفق شدن، یک session ID (به صورت Hash Code) دریافت کنه. این Session ID را باید کلاینت در هر بار تماس با سرور به سرور ارائه کنه، و سرور صحت آن را بررسی کنه، تا مطمئن بشه که کاربر ارسال کننده پیام، مجاز هست.


    وَ سَيَعْلَمُ الَّذِينَ ظَلَمُوا [آل محمد حقهم] أَيَّ مُنْقَلَبٍ يَنْقَلِبُونَ - الشعراء (227)
    و ظالمین [حق آل محمد (ص) ] به زودی خواهند دانست که به کدام بازگشتگاه بازخواهند گشت.

  37. #37

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    در صورت پیاده سازی صحیح لیست، مشکلی بوجود نمیاد. مثلا سرور میتونه برای جستجوی سریع از یک Hash Table مناسب استفاده کنه. در ضمن، اینکه کاربر یک بار لاگین کنه، و بعدش هر پیامی خواست ارسال کنه، درست نیست؛ بلکه کاربر میتونه یک بار لاگین کنه، و سپس در صورت موفق شدن، یک session ID (به صورت Hash Code) دریافت کنه. این Session ID را باید کلاینت در هر بار تماس با سرور به سرور ارائه کنه، و سرور صحت آن را بررسی کنه، تا مطمئن بشه که کاربر ارسال کننده پیام، مجاز هست.
    بله درسته . با این تفاسیر ما علاوه بر لیست Connection ها باید برای هر کاربر لاگین شده یک Session ID هم ایجاد کنیم .

    • لیست کانکشن ها برای اینکه اگه نیاز شد سرور بطور دلخواه پیغامی برای کلاینت ارسال کنه بتونه از طریق کانکشن مربوطه اینکار رو انجام بده
    • Session ID برای بررسی صحت پیغام هایی که از سمت کلاینت به سرور ارسال میشند.

    اما شرایط زیر رو در نظر بگیرید :
    یک سرور با 5 هزار کاربر آنلاین که بین هر کاربر و سرور در هر ثانیه 10 پیغام رد و بدل میشه(اعم از پیغامها ، قطعات فایل و ...) . حالا اگه قرار باشه در هر بار جا به جایی پیغام ، Session ID مربوطه بررسی بشه نهایتاً در هر ثانیه باید 50 هزار Session ID توسط سرور بررسی بشه . و اینکار پردازش سرور رو خیلی بالا میبره .

    ضمناً تا اونجایی که یادم هست در روش Non-Blocking دیگه نیاز به ایجاد چیزی مثل Session ID نبود و تنها از یک Index به عنوان مشخص کننده صحت کانکشن جاری استفاده میشد .

    چه پیشنهاد میکنید جناب کشاورز ؟

  38. #38

    نقل قول: ساخت یک برنامه ی مسنجر تحت شبکه

    ضمناً تا اونجایی که یادم هست در روش Non-Blocking دیگه نیاز به ایجاد چیزی مثل Session ID نبود و تنها از یک Index به عنوان مشخص کننده صحت کانکشن جاری استفاده میشد .
    متوجه ربط موضوع به Non-blocking یا Blocking نشدم.
    درباره Session ID، اون مقدار میتونه هر چیزی باشه، مثلا یک عدد، یا یک Hash Code که بشه از طریق آن، به سرعت در Hash Table مربوطه، کانکشن مرتبط با آن را پیدا کرد.

    یک سرور با 5 هزار کاربر آنلاین که بین هر کاربر و سرور در هر ثانیه 10 پیغام رد و بدل میشه(اعم از پیغامها ، قطعات فایل و ...) . حالا اگه قرار باشه در هر بار جا به جایی پیغام ، Session ID مربوطه بررسی بشه نهایتاً در هر ثانیه باید 50 هزار Session ID توسط سرور بررسی بشه . و اینکار پردازش سرور رو خیلی بالا میبره .
    امنیت و Performance معمولا با هم نسبت عکس دارند. شما با توجه به نیازتون باید گزینه مناسب رو انتخاب کنید. ممکنه توی برنامه شما، فقط نیاز داشته باشید که در زمان Connect شدن کاربر، اطلاعات لاگینش را بررسی کنید، و تا زمانی که Disconnect نشده، چیزی رو چک نکنید. اون دیگه بستگی به کاربرد مورد نظر شما داره.


    وَ سَيَعْلَمُ الَّذِينَ ظَلَمُوا [آل محمد حقهم] أَيَّ مُنْقَلَبٍ يَنْقَلِبُونَ - الشعراء (227)
    و ظالمین [حق آل محمد (ص) ] به زودی خواهند دانست که به کدام بازگشتگاه بازخواهند گشت.

برچسب های این تاپیک

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •