ارسآل رسآئل الى اكثر من غرفة الى الكلينتس عن طريق الإندي ؟
#1
السلام عليكم ورحمة الله

اخوآني الكرام,

اوآجه مشكلة والله المستعان,,

في الرآبط ادنى السورس + الكلينت و السرفر على شكل Exe

اود ان اعمل شات عن طريق الإندي لعدة غرف,

يعني سيكون هناك 3 شات رووم و ان كتب احد المتصلين في الغرفة 1 فلن يقرآ المكتوب الّى المتصلين في الغرفة 1 وهكذا,,

الذي يحدث معي ان المشكلة في حالة اكثر من غرفة في نفس الوقت,,

جربوا البرنامج بارك الله لكم,,

1. شغّل السرفر,,

2. ادخل 2 كلينتس او اكثر الى الغرفة 1,, كل شئ تمام, و الكونتاكت ليست يتم تطويره عادي و بالشكل المطلوب وهذا ما ****ه,,

3. ادخل مع ثالث كلينت الى الغرفة 2 في اثنآء وجود 2 من الكلينتس متصلين في الغرفة 1,,

4. ادخل برآبع كلينت الى الغرفة 2 وهنا يحدث الخلل,,
فقط رآبع كلينت يتم عمل ارسآل ال كونتاكت ليست له,, وهذه هي المشكلة,, الوآجب في هذه الحآلة ان يتم عمل update لكل المتصلين في الغرفة 2,,

السبب اظن انني اعرف,,
استخدم هذا الكود,,

PHP كود :
procedure TLogRoomSync.DoSynchronize;// Synchronization
var
  
StrItemNum, i, e, x : Integer;
  
Thread : Tlist;
  
ac : TidContext;
  
Str : Tstrings;
begin
if FRoomNumber = '0' then                      // Room 1
  
begin
    form1
.UserListBox_1.Items.Add(FUserName);
    
Str := Form1.UserListBox_1.Items;
    
ClientsIPList[0].Add(FUserIP);   //// Client IP Add To StringList
    
ClientsPortList[0].Add(FUserPort);
    
StrItemNum := 0;
  
end
else if FRoomNumber = '1' then                // Room 2
  
begin
    form1
.UserListBox_2.Items.Add(FUserName);
    
Str := Form1.UserListBox_2.Items;
    
ClientsIPList[1].Add(FUserIP);
    
ClientsPortList[1].Add(FUserPort);
    
StrItemNum := 1;
  
end
else if FRoomNumber = '2' then               // Room 3
  
begin
    form1
.UserListBox_3.Items.Add(FUserName);
    
Str := Form1.UserListBox_3.Items;
    
ClientsIPList[2].Add(FUserIP);
    
ClientsPortList[2].Add(FUserPort);
    
StrItemNum := 2;
  
end;

    
Thread:= form1.idtcpServer1.Contexts.LockList;
      
I := ClientsIPList[StrItemNum].Count - 1;  // Counts of Clients in specefik room
      
E := -1;
      for 
x := 0 to Thread.Count - 1 do        // ALL Connection With the IdTcpServer1
        
begin
          e 
:= e + 1;
          if 
e >= i then e := i;// + 1

          
ac:= Thread[x];
          If (
ac.Binding.PeerIP = ClientsIPList[StrItemNum].Strings[e]) and (IntToStr(ac.Binding.PeerPort) = ClientsPortList[StrItemNum].Strings[e])  then
          begin
            
//Showmessage('List Sent To: '+ ac.Binding.PeerIP+': '+ inttostr(ac.Binding.PeerPort));
            
ac.Connection.IOHandler.WriteLn('_CS_RoomUsersListSends');
            
ac.Connection.IOHandler.Write(Str, True,Tencoding.UTF8);
          
end;
        
end;
  
form1.idTcpServer1.Contexts.UnlockList;


end; 

وأظن ان الخلل يحدث مع المقآرنة في هذا السطر,
PHP كود :
If (ac.Binding.PeerIP = ClientsIPList[StrItemNum].Strings[e]) and (IntToStr(ac.Binding.PeerPort) = ClientsPortList[StrItemNum].Strings[e])  then 

كيف احلّ هذه المشكلة بارك الله لكم وجزآكم خيرا ,,

رآبط البرنآمج مع السورس هنا,
إقتباس :http://www.mediafire.com/?hnhnl2kzjno

ملآحظة, يمكن للإخوة تحميل الملف,
وبدآخل سرفر و الكلينت جاهز على شكل .exe ,,

اشكر الأخ o15s19 من كل قلبي :laugh:
فرّج همّ المهمومين يا الله
اللهم فك قيد اسرانا و اسرى المسلمين
الرد
#2

لم أطلع على الملفات المصدرية لضيق الوقت وعدم وجود دلفي 2009/2010 بالجهاز الحالي
فقط جربت الملفات التنفيدية
1- تنفيذ Server
2- تنفيذ Client مرتين وانشاء مستخدمين جدد
3- دخول الغرفة 1 كلاهما
4- عند خروج مستخدم بالضغط على Back ثم عودته لنفس الغرفة يظهر مرتين
5- تكرير 4 ثلاث مرات يصبح نفس المستخدم موجود بClient وكذلك بListBox بServer

لا ادري كيف تفكيرك او نظرتك للامر
من المفروض يضاف المستخدم للغرفة عند دخولها و يحذف عند الخروج منها
من المفروض وجود جداول سواء بClient او Server تحتوي معلومات الغرف والمتصلين
وهناك وقت معين ان لم يرسل المتصل رسالة تتحول حالته الى مشغول/غائب او ما شابه
إقتراح: ما رايك بوضع مشروعك بقسم المشاريع الجماعية ومنه يمكن مناقشته من البداية
والسلام عليكم
الرد
#3
وعليكم السلام,

اخي الكريم,
إقتباس :لا ادري كيف تفكيرك او نظرتك للامر
من المفروض يضاف المستخدم للغرفة عند دخولها و يحذف عند الخروج منها

هذا صحيح, بالنسبة لهذا الآمر لم اقم به لحد الآن, + عمله يسير ان شاء الله,

امّا بالنسبة للخطوآت الذي قمت انت بها, فهي تنيجة عن النقص كما ذكر في الأعلى,,
ليس هو الخلل الذي كنت اقصده,,

للتوضيح,,
بعد عمل كونكت في السرفر,, (هناك ثلاث من ListBox, وآحد لكل غرفة يظهر اسمآء المتصلين الموجودين حالياً) هناك فقط 3 غرف محادثة في هذا المشروع

افتح 3 من الكلينتس (يمكن انشآء معرّفات جديدة او استدخام كل المعرفات Admin)

ادخل على الغرفة 1 لكل الكليتس الثلآثة في الأعلى,,

ماذا يحدث,,؟
عند دخول اول كلينت فيكون عندها موجود 1 متصل في الكلينت ليست للكلينت الأول,
بعد دخول ثاني كلينت على الغرفة 1 يتم عمل Update ل Contact List للكلينت الأول و الثاني,
عند دخول ثالث كلينت الى الغرفة 1 يتم عمل Update لل Concact List او RoomList في الكلينت الأول و الثآني و الثآلث,,

الآن نعمل تقريبا نفس الشئ,,
دع الأمور كما هي, وأضف الى ذلك فتح 3 كلينتس جدد,
ادخل في هذه المرة بالثلآثة على الغرفة 2,,

ماذا يحدث,,؟
الآن عندنا 1 سرفر يعمل, + 6 من الكلينتس,
الثلآثة في البدآية هم في الغرفة 1,,
وآخر ثلآثة هم في الغرفة 2,,

عند دخول الكلينت الرآبع ال الغرفة 2 يتم عمل Uppdate لل Contact List , ويتم جلب 1 User في الغرفة 2,,
عند دخول الكلينت الخامس على الغرفة 2 يتم عمل Uppdate لل Contact List فقط للكلينت الخآمس, الكلينت الرآبع لا يتم عمل Uppdate لل Contackt List له, هنا الخلل, لماذا ؟؟؟
و أخيرا عند دخول الكلينت رقم 6 الى الغرفة 2 يتم عمل Uppdate لل Contact List فقط للكلينت الأخير وليس كل الكينتس وهاذا هو الخلل الذي لا اعرف كيف اصلحه والله المستعان,, (الصحيح هو ان يتم عمل Update لل Contact List لكل الكلينتس المتصلين بالغرفة 2)

ان شاء الله الأمور وآضحة الآن,

إقتباس :إقتراح: ما رايك بوضع مشروعك بقسم المشاريع الجماعية ومنه يمكن مناقشته من البداية
مشروعي الآن على وشك النهآية, على الأقل للإصدار Beta,, Smile (وآظن ان الخلل في الأعلى هو الخلل الأخير الذي اصادفه في مشروعي قبل ال Beta)
وبعدها لكل حدث حديث ان شاء الله (ولكن ابشر بكل خير)

بارك الله لكم جميعا,
والسلام عليكم ورحمة الله
فرّج همّ المهمومين يا الله
اللهم فك قيد اسرانا و اسرى المسلمين
الرد
#4

القيت نظرة سريعة على ما كتبت
جرب تغيير هذا
كود :
I := ClientsIPList[StrItemNum].Count - 1; E := -1; for x := 0 to Thread.Count - 1 do begin e := e + 1; if e >= i then e := i;// + 1 ac:= Thread[x]; If (ac.Binding.PeerIP = ClientsIPList[StrItemNum].Strings[e]) and (IntToStr(ac.Binding.PeerPort) = ClientsPortList[StrItemNum].Strings[e]) then begin ac.Connection.IOHandler.WriteLn('_CS_RoomUsersListSends'); ac.Connection.IOHandler.Write(Str, True,Tencoding.UTF8); end; end;
بهذا واخبرني
كود :
I := ClientsIPList[StrItemNum].Count - 1; for x := 0 to Thread.Count - 1 do begin ac:= Thread[x]; for e:=0 to i do If (ac.Binding.PeerIP = ClientsIPList[StrItemNum].Strings[e]) and (IntToStr(ac.Binding.PeerPort) = ClientsPortList[StrItemNum].Strings[e]) then begin ac.Connection.IOHandler.WriteLn('_CS_RoomUsersListSends'); ac.Connection.IOHandler.Write(Str, True,Tencoding.UTF8); end; end;
لم اجربه /لا دلفي بهذا الجهاز
الرد
#5
الله يبارك فيكم اخي العزيز ديلتا,
هذا هو ما كنت احاول فيه و ابحث عنه,,
تم حل المشكلة بالكود الذي وضعته,
جزاك ربي خير الجزآء,
فرّج همّ المهمومين يا الله
اللهم فك قيد اسرانا و اسرى المسلمين
الرد
#6
أسف على وصولي متأخرا :oops: و لكن لدي بعض التعقيبات
1) في هذا الكود

كود :
if FRoomNumber = '0' then // Room 1 begin form1.UserListBox_1.Items.Add(FUserName); Str := Form1.UserListBox_1.Items; ClientsIPList[0].Add(FUserIP); //// Client IP Add To StringList ClientsPortList[0].Add(FUserPort); StrItemNum := 0; end else if FRoomNumber = '1' then // Room 2 begin form1.UserListBox_2.Items.Add(FUserName); Str := Form1.UserListBox_2.Items; ClientsIPList[1].Add(FUserIP); ClientsPortList[1].Add(FUserPort); StrItemNum := 1; end else if FRoomNumber = '2' then // Room 3 begin form1.UserListBox_3.Items.Add(FUserName); Str := Form1.UserListBox_3.Items; ClientsIPList[2].Add(FUserIP); ClientsPortList[2].Add(FUserPort); StrItemNum := 2; end;

و بغض النظر عن الكود يمكنك استخدام Case of بدل استخدام الكثير من ال if لأن ال if ابطأ بحالة هناك ضغط على السرفر

2)
ألاحظ أنك تستخدم ClientsIPList و ClientsPortList يعني قائمتين
طيب أنت فينك تستخدم قائمة واحدة تضم كلا الاثنين لاحظ هذا الكود
هنا لإضافة على القائمة مع ملاحظة أن ال '=' يمكنك استبدالها بشئ أخر و لكن هذه المتعارف عليها

كود :
ClientsIPList[0].Add(FUserName + '=' + FUserPort) ;

و هنا للاستدعاء
كود :
FUserName := ClientsIPList[0].Names[1] ; FUserPort := ClientsIPList[0].ValueFromIndex[1] ;

لأن وجود قائمتين يجعل مع كثرة عدد الاجهزة القائمة تدخل بالحيط (مجربها مع 16 جهاز) تانيا حل القائمة الواحدة أريح و أخف للبرنامج

3)كمان لاحظت(كترت ملاحظاتي مو هيك ) إن السرفر يجيب على الكلاينت في عملية ال Sync حاول وضعها مباشرة و اجعل ال Sync فقط بحالة تريد اظهار شئ على GUI و لا تدخله في شئ أخر لكي لا يحصل ما يسمى Bottle Neck

هذا مبدأئيا و نظرة سطحية سلامي
الرد
#7
الأخ o15s19,,

اشكرك كثيرا على ملآحظاتك هذه, فهي مهمة جدا بالنسبة لي,

فيما يخص النقطة 1 و النقطة 2 فالأمر وآضح, لم اجرب 2 بعد ولكن سأفعل هذا الآن ان شاء الله,,

امّا نقطة 3,,
لم افهم ماذا تقصد بارك الله لك,
إقتباس :حاول وضعها مباشرة

اين اضعها ؟ في الحدث OnExcute ؟

إقتباس :(كترت ملاحظاتي مو هيك )

بالعكس اخي, ان كان هناك مزيد من الملآحظات فقلها بارك الله لك وأكون لك من الشآكرين,
فرّج همّ المهمومين يا الله
اللهم فك قيد اسرانا و اسرى المسلمين
الرد
#8
في النقطة الأخيرة العملية فقط تبديل و يصبح الأمر افضل
اجعل الاجابة على الكلاينت مباشرة في حدث OnExecute ثم قم باضافته إلى القائمة (اقصد Listbox)من خلال ال Sync .
و هنا لا يتم في ال Sync اجابة على الكلاينت و هذا يريح كلا السرفر و الكلاينت و على ما اظن ارسسال القائمة أفضل لأنو ما بتكون بعدك ضايف الكلاينت الجديد على القائمة. و هذا يعني أنك سترسل القائمة مباشرة .

سلامي
الرد
#9
يعني اخي الكريم, سامحني على كثرة اسئلتي, لكن,
هل تقصد انني اضع الكود في ال Sync, (لم استخدم ال Case بعد)
PHP كود :
if FRoomNumber = '0' then                      // Room 1
  
begin
    form1
.UserListBox_1.Items.Add(FUserName);
    
Str := Form1.UserListBox_1.Items;
    
ClientsIPList[0].Add(FUserIP);   //// Client IP Add To StringList
    
ClientsPortList[0].Add(FUserPort);
    
StrItemNum := 0;
  
end
else if FRoomNumber = '1' then                // Room 2
  
begin
    form1
.UserListBox_2.Items.Add(FUserName);
    
Str := Form1.UserListBox_2.Items;
    
ClientsIPList[1].Add(FUserIP);
    
ClientsPortList[1].Add(FUserPort);
    
StrItemNum := 1;
  
end
else if FRoomNumber = '2' then               // Room 3
  
begin
    form1
.UserListBox_3.Items.Add(FUserName);
    
Str := Form1.UserListBox_3.Items;
    
ClientsIPList[2].Add(FUserIP);
    
ClientsPortList[2].Add(FUserPort);
    
StrItemNum := 2;
  
end; 

وبعدها اضع الكود هذا في قسم ال OnExecute ؟
PHP كود :
Thread:= form1.idtcpServer1.Contexts.LockList;
I := ClientsIPList[StrItemNum].Count - 1;
for 
x := 0 to Thread.Count - 1 do
  
begin
  ac
:= Thread[x];
  for 
e:=0 to i do
  If (
ac.Binding.PeerIP = ClientsIPList[StrItemNum].Strings[e]) and (IntToStr(ac.Binding.PeerPort) = ClientsPortList[StrItemNum].Strings[e])  then
    begin
      ac
.Connection.IOHandler.WriteLn('_CS_RoomUsersListSends');
      
ac.Connection.IOHandler.Write(Str, True,Tencoding.UTF8);
    
end;
  
end;
form1.idTcpServer1.Contexts.UnlockList; 
فرّج همّ المهمومين يا الله
اللهم فك قيد اسرانا و اسرى المسلمين
الرد
#10
عليك نور
هذا ما قصدته
الرد


التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم