PDA

View Full Version : سوال: کاربران آنلاین،آفلاین کردن یک کاربر



alias136790
جمعه 16 فروردین 1392, 16:01 عصر
من دارم با یه برنامه تحت شبکه با سی شارپ و پایگاه داده اس کیو ال کار میکنم.

1.من میخوام بدونم چجوری میشه تشخیص داد که چه کاربری آنلاین هست تا جلوی این که بصورت همزمان
یه کاربر مثلا حامد دوبار وارد بشه جلوگیری کرد و همچنین این کاربران رو یه جا تو برنامه نمایش بدم؟

2. و چطوری میتونم یه کاربر خاص مثلا حامد رو آفلاین کنم؟


من میخوام کارای بالا رو تو برنامه ام انجام بدم ، نه با sql server management.
و میخوام راهنماییم کنید چه کارایی رو دیتابیس و برنامه انجام بدم.

GoodLuck

debugger
جمعه 16 فروردین 1392, 16:24 عصر
یک فیلد boolean تعریف کن هنگامی که لاگین کرد اونو 1 کن . وقتی خروج کرد اونو 0 کن . با چک کردن مقدار اون فیلد می تونی بفهمی انلاینه یا افلاینه

alias136790
جمعه 16 فروردین 1392, 22:03 عصر
خب من همین کار رو میکنم اما اگه کاربر هنگام کار با برنامه سیستمش هنگ کنه یا سرور خاموش باشه، در این صورت مقدار این فیلد 1 باقی میمونه.
و دفعه بعد که کاربر بخواد وارد بشه، چون مقدار فیلد 1 هست اجازه ورود به کاربر رو نمیده.( هنگام ورود یک کاربر من چک میکنم مقدار فیلد این کاربر 1 هست یا صفر)

حتی اگه این مشکل رو هم بپذیرم.
سؤال دومم حل نمیشه چون میخوام بعد از این که یه کاربر رو آفلاین کردم ، کاربر نتونه با برنامه کار کنه( به این صورت که یا برنامه بسته بشه یا اینکه ارتباط کاربر با دیتابیس قطع بشه) ( من دیدم با استفاده از برنامه sql server management تو قسمت Activity Monitor با استفاده از Kill Process میشه ارتباط کاربر با دیتابیس رو قطع کرد ، اما چون تو سیستم کاربر این برنامه رو نمیخوام نصب کنم پس این روش جواب نمیده)

GoodLuck

debugger
شنبه 17 فروردین 1392, 00:05 صبح
شما علاوه بر اینکه هنگامی که لاگین کرد اونو 1 کن . وقتی خروج کرد اونو 0 کنی ، باید از طریق سرور ، همه ی کلاینت ها را پینگ کنی اگر در دسترس بودن یعنی روشن هستند ولی در دسترس نبودن یعنی خاموشن . اگر دیدی خاموشن مقدار فیلد boolean را تغییر بدی به حالت افلاین (یعنی 0). برای مشکل هنگ کردن کلاینت راهی نیست درستش اینه که در حالت انلاین بمونه . طرف میبینه سیستم هنگ کرده مجبور میشه ریستارت کنه سرور پینگ می کنه می بینه جواب نیومد . اونو به حالت افلاین در میاره. --- خب حالا حالتی را در نظر میگیریم که سرور خاموش میشه . در این صورت کلاینت باید سرور را پینگ کنه (این امکان باید باشه) اگر دید سرور در دسترس نیست . باید سریعا کاربر فعلی را Block بشه و نتونه با برنامه کار کنه تا وقتی که سرور بالا بیاد . وقتی سرور بالا اومد موقع لاگین ادمین باید وضعیت همه ی کلایت ها را آفلاین کنی و باید کلاینت ها دوباره لاگین کنند . چون راه درستش اینه.

جواب سوال دوم : وقتی یک کاربر را افلاین کردی از طریق سرور . باید به کلاینت یک message بفرستی . کلاینت با دریافت msg باید کاربر را بلاک کند

alias136790
شنبه 17 فروردین 1392, 00:39 صبح
(شما علاوه بر اینکه هنگامی که لاگین کرد اونو 1 کن . وقتی خروج کرد اونو 0 کنی ، باید از طریق سرور ، همه ی کلاینت ها را پینگ کنی اگر در دسترس بودن یعنی روشن هستند ولی در دسترس نبودن یعنی خاموشن . اگر دیدی خاموشن مقدار فیلد boolean را تغییر بدی به حالت افلاین (یعنی 0).)

خب من چطوری کلاینت ها رو پینگ کنم ؟ من تا حالا پینگ نکردم.

و چجوری یه کلاینت سرور رو پینگ کنه و در صورت لزوم کاربر بلوکه بشه؟( چون کاربر میتونه تو هر فرمی باشه )

(جواب سوال دوم : وقتی یک کاربر را افلاین کردی از طریق سرور . باید به کلاینت یک message بفرستی . کلاینت با دریافت msg باید کاربر را بلاک کند)

خب من چطوری میتونم به کلاینت یه پیام بدم؟ و باز چطوری بلوکه اش کنم؟

GoodLUck

debugger
شنبه 17 فروردین 1392, 01:08 صبح
ادرس ip کلاینت مورد نظر را میدین

//You'll need this pinvoke signature as it is not part of the .Net framework
[DllImport("iphlpapi.dll", ExactSpelling = true)]
public static extern int SendARP(int DestIP, int SrcIP,
byte[] pMacAddr, ref uint PhyAddrLen);

//These vars are needed, if the the request was a success
//the MAC address of the host is returned in macAddr
private byte[] macAddr = new byte[6];
private uint macAddrLen;

//Here you can put the IP that should be checked
private IPAddress Destination = IPAddress.Parse("127.0.0.1");

//Send Request and check if the host is there
if (SendARP((int)Destination.Address, 0, macAddr, ref macAddrLen) == 0)
{
//SUCCESS! Igor it's alive!
}

شما حتی می تونید کل ip های موجود در lan را بیابید و یکی یکی اونا رو پینگ کنید یا به صورت دستی از قبل موقع کانفیگ برنامه ادرس های ای پی را ست بکنی

برای بلاک کردن هم راه های زیادی هست . سریعترین روش اینه

Thread.CurrentThread.Suspend();

در مورد ارسال message هم دنبال مباحث

NetworkStream

socket programming

باشین

مثال برای ارسال اینگونه هست

public void SendMessage(TcpClient client, string message)
{

byte[] buffer = Encoding.ASCII.GetBytes(message);

NetworkStream stream = client.GetStream();
stream.Write(buffer, 0, buffer.Length);

client.Close();
}

برای دریافت هم تقریبا اینطوری میشه (کد های دقیق را خودت جستجو کن)

var stream = client.GetStream();
while (true)
{
byte[] buffer = new byte[2048];
int bytesRead = stream.Read(buffer, 0, 2048);

if (bytesRead > 0)
{
StringBuilder sb = new StringBuilder();
string v = Encoding.ASCII.GetString(buffer);

}
}

alias136790
شنبه 17 فروردین 1392, 01:47 صبح
این که خیلی پیچیده شد، علاوه بر موارد بالا من باید آی پی کلاینت ها رو هم داشته باشم(که ندارم).
برای دریافت مسیج هم قبلا گفتم کاربر ممکنه تو هر فرمی فعالیت داشته باشه، از تابعی که دادین کجا میشه استفاده کرد؟
شما مطمئنین روش اصولیش اینه؟، تا حالا امتحان کردین؟

debugger
شنبه 17 فروردین 1392, 07:57 صبح
این که خیلی پیچیده شد، علاوه بر موارد بالا من باید آی پی کلاینت ها رو هم داشته باشم(که ندارم).
برای دریافت مسیج هم قبلا گفتم کاربر ممکنه تو هر فرمی فعالیت داشته باشه، از تابعی که دادین کجا میشه استفاده کرد؟
شما مطمئنین روش اصولیش اینه؟، تا حالا امتحان کردین؟

من نمیدونم شما چه برنامه ای میخواهید بنویسید .اما فکر می کنم درک درستی از نرم افزار مربوطه نداشتید . سرور چطور میتونه به کلاینت و کلاینت چطور می تونه به سرور دسترسی داشته باشه ؟؟؟؟ بجز ip راه دیگه ای هم هست ؟؟؟؟؟ اگر هست خوشحال میشم به منم یاد بدین

در مورد اون قسمتی که bold کردم . شما باید یک مقدار bool داشته باشین که توی کل فرم ها و هر کجای برنامه بهش دسترسی داشته باشین . دیگه این مباحث مربوط به برنامه نویسی و روش شما دارد و کار شدنی هست

اصولی ترین و سریعترین روش در یک شبکه برای گفتگو همین روش است .

alias136790
شنبه 17 فروردین 1392, 14:19 عصر
سخت نگیرین. این اولین کارم درباره شبکه است. من با آی پی کار نکردم. تنها ارتباطی که در حال حاضر بین کلاینت و سرور هست، از طریق دیتابیس هست و بس.
حتی کانکت اسرینگ برای اتصال کلاینت ها به سرور هم ، نام سرور هست. این کاریه که من میکنم و برنامه ام آزمون گیر/آزمون ساز هست . با سه سطح کاربری مدیر، معلم و دانش آموز.
من نمیگم روش شما شدنی نیست، فقط میگم پیچیده است و کلی دردسر، مثلا من تو برنامه مدیر، آنلاین بودن دانش آموزان و معلمان رو نشون میدم،حالا مدیر میاد اطلاعات دانش آموزان و معلمان رو وارد میکنه و از برنامه خارج میشه و مدیر ممکنه طی یه هفته یا دو هفته فقط یه بار برنامه رو باز کنه، این معلم و دانش آموز هستند که همیشه از برنامه استفاده میکنند، وقتی که برنامه مدیر بسته است(سرور رو سیستم مدیر در نظر گرفتم) و معلم هنگام کار با برنامه سیستمش هنگ کنه، مقدار فیلد آنلاین اون معلم 1 باقی میمونه و باز همون مشکل صفر کردن این فیلد( اگه برنامه مدیر باز باشه میشه بقول شما پینگ کرد، ولی الان برنامه مدیر بسته است و تنها اس کیو ال سرور فعال هست)

GoodLuck

alias136790
دوشنبه 19 فروردین 1392, 17:27 عصر
دوستان، روش دیگه ای غیر از این روش که کاربر گرامی debugger گفتن هم هست؟
یعنی اینکه بتونم کاربران آنلاین رو با استفاده از خوده برنامه microsoft sql express تشخیص بدم و همینطور بتونم یه کاربر خاص رو آفلاین کنم. اما نیازی به استفاده از سوکت نباشه. در حال حاضر من برای تشخیص آنلاین بودن یه کاربر ، یه فیلد بولین تو جدول کاربران از دیتابیس قرار دادم که اگه کاربری آنلاین شد مقدار این فیلد 1 و وقتی آفلاین شد مقدار صفر رو برگرودنه، اما بدلیل مشکلات و دردسرهایی که این روش داره ، میخوام از این روش استفاده نکنم.
پس دوستان و کاربران ، خصوصا با تجربه ها لطفا راهنمایی کنید، برنامه ام گیر این مشکل کاربران آنلاین و آفلاین هست.

zoofa
دوشنبه 19 فروردین 1392, 20:31 عصر
سلام
به جای اون فیلد بولین یه فیلد از نوع datetime واسه هر کاربر بذارید و هر 1 دقیقه از کلاینت تاریخ اون رو آپدیت کنید.
اگه کلاینتی هنگ کرد و یا ارتباطش با سرور قطع شد مقدار اون فیلد از زمان جاری بیشتر از 1 دقیقه که بشه کاربر آفلاین شده.
واسه اینکه یه کاربری رو آفلاین کنی هم می تونی یه فیلد بولین بذاری و هنگامی که تو کلاینت میخای تاریخ فیلد آنلاین بودن رو ست کنی قبلش اون فیلد بول رو چک کنی و اگه ترو بود برنامش رو اگزیت کنی و هنگام لاگین مقدارش رو فالس کنی که به مشکل برنخوری.

FastCode
دوشنبه 19 فروردین 1392, 21:03 عصر
به جای صفر کردن بولین میتونی مقدار datetime رو null کنی.


البته من خودم کار دیگه کردم.
یک session manager کامل نوشتم.(با سوکت)
(فکر نمیکنم شما وقتش رو داشته باشی/۴۰~۳۰ هزار خط)
102539


//SUCCESS! Igor it's alive!نه عزیزم
It's dead jim.
روش شما از پشت سویچ و روتر جواب نمیده

alias136790
دوشنبه 19 فروردین 1392, 22:47 عصر
سلام
به جای اون فیلد بولین یه فیلد از نوع datetime واسه هر کاربر بذارید و هر 1 دقیقه از کلاینت تاریخ اون رو آپدیت کنید.
اگه کلاینتی هنگ کرد و یا ارتباطش با سرور قطع شد مقدار اون فیلد از زمان جاری بیشتر از 1 دقیقه که بشه کاربر آفلاین شده.
واسه اینکه یه کاربری رو آفلاین کنی هم می تونی یه فیلد بولین بذاری و هنگامی که تو کلاینت میخای تاریخ فیلد آنلاین بودن رو ست کنی قبلش اون فیلد بول رو چک کنی و اگه ترو بود برنامش رو اگزیت کنی و هنگام لاگین مقدارش رو فالس کنی که به مشکل برنخوری.

حالا یه سؤال: اینکه هر 1 دقیقه تاریخ رو آپدیت کنه، چطوری ؟ میشه اینکار رو با استفاده از triger تو دیتابیس انجام بدم؟( ینی هر یه دقیقه triger تاریخ رو آپدیت کنه )اینکه یه timer باید بذارم اما چطوری باهاش کار کنم ؟ کاربر کلاینت ممکنه تو هر فرمی باشه!!
و یه سؤال کوچیک اما مهم: اینکار(آپدیت تاریخ هر یه دقیقه) سرعت کار با برنامه رو پایین نمیاره؟ فکر کن 30 کاربر کلاینت آنلاین هستن.


البته من خودم کار دیگه کردم.
یک session manager کامل نوشتم.(با سوکت)
(فکر نمیکنم شما وقتش رو داشته باشی/۴۰~۳۰ هزار خط)

این برنامه ای که نوشتی ، راست کار من میاد؟ فروشیه یا اینکه میتونی بخشی از برنامت رو در اختیار ما بذاری؟

GoodLuck

FastCode
دوشنبه 19 فروردین 1392, 23:06 عصر
حالا یه سؤال: اینکه هر 1 دقیقه تاریخ رو آپدیت کنه، چطوری ؟ میشه اینکار رو با استفاده از triger تو دیتابیس انجام بدم؟( ینی هر یه دقیقه triger تاریخ رو آپدیت کنه )اینکه یه timer باید بذارم اما چطوری باهاش کار کنم ؟ کاربر کلاینت ممکنه تو هر فرمی باشه!!
و یه سؤال کوچیک اما مهم: اینکار(آپدیت تاریخ هر یه دقیقه) سرعت کار با برنامه رو پایین نمیاره؟ فکر کن 30 کاربر کلاینت آنلاین هستن.



سرعت رو که پایین میاره ولی فکر نمیکنم مقدارش قابل ملاحظه باشه.
باید سمت کلاینت دستور آپدیت رو بنویسید.


این برنامه ای که نوشتی ، راست کار من میاد؟ فروشیه یا اینکه میتونی بخشی از برنامت رو در اختیار ما بذاری؟

GoodLuck
این برنامه هدف اصلیش این نیست و متاسفانه فروشی هم نیست (TradeSecret) و البته فکر نمیکنم بتونید ازش استفاده کنید چون باید کلاینتتون رو از اول برای این سیستم بنویسید.
فقط نمونه گزاشتم که ببینید میشه.

alias136790
دوشنبه 19 فروردین 1392, 23:21 عصر
خیلی خب سمت کلاینت باشه.
حالا برای این آپدیت تاریخ، باید یه تایمر بذارم، من نمیدونم این تایمر رو کجا تعریف کنم؟ فکر کنم تو یه کلاس عمومی.
و بعد تو هر فرم از این کلاس استفاده کنم، این کار درسته دیگه؟ و اگه اطلاعات دارین بیشتر راهنمایی کنین،چون اولین باره این رو تجربه میکنم.

FastCode
دوشنبه 19 فروردین 1392, 23:39 عصر
یک کلاس تعریف کنید به اسم مثلا KeepAlive
در Program یک نسخه ازش ایجاد کنید.
بعد از login فعالش کنید و بعد از خروج از بین ببریدش
در اون کلاس یک ترد تعریف کنید که هر چند ثانیه یک StoredProcedure رو سمت سرور اجرا کنه.
Thread.Sleep استفاده کنید.

باید از StoredProcedure استفاده کنید در غیر این صورت در صورت اختلاف ساعت سرور و کلاینت کلا این روش جواب نمیده

alias136790
سه شنبه 20 فروردین 1392, 00:42 صبح
بعد از login فعالش کنید و بعد از خروج از بین ببریدش

من بیام تو program یه نسخه ازش ایجاد کنم ینی KeepAlive KA = new KeepAlive();
حالا چطوری فعالش کنم و از بین ببرمش؟

و تو کلاس از ترد به این صورت استفاده کنم درسته؟
while (true)
{
Thread.Sleep(6000);
MessageBox.Show("true");
}

FastCode
سه شنبه 20 فروردین 1392, 03:42 صبح
آره

و در آخر ترد رو Abort کن

bitcob589
سه شنبه 20 فروردین 1392, 12:46 عصر
یک کلاس تعریف کنید به اسم مثلا KeepAlive
در Program یک نسخه ازش ایجاد کنید.
بعد از login فعالش کنید و بعد از خروج از بین ببریدش
در اون کلاس یک ترد تعریف کنید که هر چند ثانیه یک StoredProcedure رو سمت سرور اجرا کنه.
Thread.Sleep استفاده کنید.

باید از StoredProcedure استفاده کنید در غیر این صورت در صورت اختلاف ساعت سرور و کلاینت کلا این روش جواب نمیده

درون StoredProcedure چه نوع دستوری نوشته شود
اگر کاربر به جای کلیک دکمه خروج صفحه close کرد چگونه کلاس بین ببریم

alias136790
سه شنبه 20 فروردین 1392, 14:16 عصر
یه سؤال دیگه، تو کلاس KeepAlive من یه تابع نوشتم به این صورت
public static void st()
{
bool m = true;
while (m)
{
Thread.Sleep(6000);
if (DateTime.Now.TimeOfDay.Minutes == 01)
MessageBox.Show("true");
else
{
m = false;
break; //break;
}
}
Application.Exit();
}


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

FastCode
سه شنبه 20 فروردین 1392, 16:22 عصر
گفتم که باید از ترد استفاده کنید.
اون m و if و Application.Exit() و else و MessageBox هم اضافست.
فقط باید یک SQLCommand که SP رو اجرا میکنه Execute کنید.

alias136790
سه شنبه 20 فروردین 1392, 22:17 عصر
میدونم sp رو باید فراخونی کنم. اما سؤال اینجاست چجوری هر 1 دقیقه فراخوانیش کنم، از اون طرف کاربر بتونه به کارای دیگه برنامه هم برسه؟ وقتی من از
حلقه While و Thread.Sleep(6000 استفاده میکنم، کلا برنامه میخوابه و اجازه هیچ کاری به من نمیده.
اگه بتونین یه بار کامل راهنمایی کنین، زحمت رو کم میکنم، مشکل ما هم حل میشه.

FastCode
سه شنبه 20 فروردین 1392, 23:13 عصر
مجبور شدم IDE باز کنم
public class KA
{
Thread thread;
AutoResetEvent are;
bool started;
public bool Started {
get {
return started;
}
}

internal KA()
{
started = false;
are = new AutoResetEvent ();
thread = new System.Threading.Thread (Loop);
}
void Loop ()
{
while (!are.WaitOne(10000)) {
//excute SP here
}
}
internal void Start()
{
if(started) throw new InvalidOperationException("KeepAlive aleady started.");
started = true;
thread.Start();
}
internal void Stop()
{
if(!started) throw new InvalidOperationException("Cannot stop an already stopped KeepAlive.");
are.Set();
thread.Join();
}
}


شما هم بهتره یک مقدار راجع به ترد ها مطالعه کنی.
در غیر این صورت یک i7 با celeron فرقی برای بنامت نخواهد داشت.