PDA

View Full Version : گفتگو: كدي براي آگاهي از قطع اتصال TCP



elyas_delshadnbe
شنبه 10 آبان 1393, 11:14 صبح
سلام دوستان
من برنامه اي نوشتم كه ي سرور و چندتا كلاينت tcp داره. كلاينت ها به سرور متصل ميشن و براش داده ميفرستن. حالا تصميم دارم يه برنامه رو به اين برنامه ها اضافه كنم تا هر دو طرف از قطع اتصالشون آگاه بشن. هم كلاينت ها و هم سرور.كسي نظري داره يا كمكي ميكنه كه اين كارو انجام بديم؟

elyas_delshadnbe
شنبه 10 آبان 1393, 11:50 صبح
روال پيشنهادي خودم اينه كه يه تايمر هر دو طرف گذاشته بشه و كلاينت يه پيام خاص رو بفرسته و سرور پاسخ بده و اين كار مثلا در 10 ثانيه دوبار تكرار بشه و اگه كلاينت پاسخ نگرفت يا سرور پيامي دريافت نكرد بفهمن هردوشون كه اتصالشون قطع شده. هيچكي نيس ي نظري بده لااقل؟

pedram.11
شنبه 10 آبان 1393, 11:56 صبح
روش درسته اما در سمت سرور. که به اصطلاح توی یه بازه زمانی پینگ میشه. اگه پینگ نشد اون کانکشن حذف میشه. یعنی سرور چک میکنه که توی اون بازه زمانی دیتایی بهش ارسال میشه یا نه اگه نه اون کانکشن رو حذف میکنه. اما در سمت کلاینت در صورتی که طول دیتای دریافت شده صفر باشه یا exception رخ بده کانکشن بسته میشه

elyas_delshadnbe
شنبه 10 آبان 1393, 12:19 عصر
آره درسته. واسه كلاينت 0 باشه اوكيه. ولي سمت سرور چون علاوه بر داده هاي اصلي كه كلاينت ميفرسته هر 5 ثانيه هم يه داده ديگه كلاينت ميفرسته كه همون بسته ي آگاهي از اتصالشونه. واسه تفكيكشون چي به ذهنت مي رسه؟

pedram.11
شنبه 10 آبان 1393, 12:29 عصر
تفکیک بحثش جداس روش زیاده. میتونی کل الگوی دیتا رو به xml تغییر بدی یا اینکه فلگ بذاری و توکن توکن پردازش کنی.
البته ببنید گفتم داده ارسال بشه در یک بازه زمانی. یعنی شما میتونید هر یک دقیقه یک بایت به سرور ارسال کنید تا سرور زمان آخرین دیتای دریافتی رو ریست کنه و کانکشن رو نبنده. اینطوری نیاز به پردازش نداره. البته بگم کلاینت وقتی باید دیتای جلوگیری از قطع اطلاعات رو ارسال کنه که در حالت idle باشه(و گرنه که خود داده های اصلی که ارسال میشن باعث جلوگیری از دیسکانت شدن میشن :لبخند:) که در اینصورت مابین دیتای اصلی تداخل پیش نمیاد و همچنین تبادل دیتا کاملا بهینه میشه

elyas_delshadnbe
شنبه 10 آبان 1393, 12:37 عصر
دمت گرم.نظر خوبي بود.پس يه كار ديگه مي كنم.كلاينت كه داده هاي اصليشو ميفرسته كه هيچ بهش كار نداريم.
واسه سرور يه زمان سنج تعريف ميكنم كه قبل Receive صفر باشه. و روي خط Receive به مدت 5 ثانيه توقف كنه. اگه چيزي دريافت شد كه حله اگرم نشد يني يا كلاينت داده نداره ديگه يا هم كه Disconnect شده حالا به هر دليلي و اگه اينجوري شد ما سوكت اون كلاينتو مي بنديم. نظرت چيه؟شدنيه؟

pedram.11
شنبه 10 آبان 1393, 13:03 عصر
آره موفق باشی :تشویق:

elyas_delshadnbe
شنبه 10 آبان 1393, 13:11 عصر
البته الان پشيمون شدم. سيستمي كه من ميخام نبايد سرور كانكشن كلاينت رو قطع كنه.شايد كلاينت يه روز هم نخاد داده بفرسته. كانكشنش بايد حفظ بشه ولي اگه مثلا كابل قطع شد يا داده نيومد بهد 5 ثانيه جفتشون ميفهمن كه قطع شدن. اينو ميخام من. كدمو كامل اگه ميخاي بذارم برات يه نگاه بكن ببين چيزي ميتوني واسه همين قضيه بهش اضافه كني؟

pedram.11
شنبه 10 آبان 1393, 13:39 عصر
اگه در سمت سرور اینکارو نکنید و کانکشن هایی که در یک بازه خاصی دیتا ارسال نکردن رو چک و حذف نکنید مشکل پیش میاد. مثلا فرض کنید یکی بدون اینکه دیسکانکت شه برنامه رو میبنده. اینطوری سرور نمیدونه که کلاینت دیس شده یا نه. در اینصورت یکی یکی کانکشن های بی مصرف در حافظه اشباه میشن که احتمالا سرور میاد پایین :گیج:

elyas_delshadnbe
یک شنبه 11 آبان 1393, 08:25 صبح
اينا برنامه كامل سمت سرور و كلاينت منن. برنامه كلاينت كم و كسر نداره ولي سرور هنوز كار داره. واسه مديريت كلاينتهام هيچكار نكردم. اگه ي لطف كني يه نگا بندازي ممنون ميشم.

elyas_delshadnbe
یک شنبه 11 آبان 1393, 08:28 صبح
در مورد برنامه كلاينت توضيح اينكه شماره پورت بذار همون 11000 باشه. چون واسه سرور همونو تعريف كردم. بقيشو ميشه تغيير داد و اينكه بعد از شروع كار تعداد 1 تا مقداري كه وارد شده بسته با سايز وارد شده فرستاده ميشه. اجرا كني واضحه متوجه ميشي. فقط سرور خالي از ايراد نيست و منم دنبال رفع ايرادات سرورم

elyas_delshadnbe
یک شنبه 11 آبان 1393, 11:24 صبح
در مورد برنامه سرور هم ي سري تغييرات دارم ميدم كه بعدا ميذارم. منتظرتم داداش پدرام

pedram.11
یک شنبه 11 آبان 1393, 17:13 عصر
سلام کداتونو دیدم. تقریبا پروژه سرور رو بازنویسی کردم :لبخند: سعی کنید توی این مدل برنامه ها بجای AcceptSocket از BeginAcceptSocket و بجای Reveive از BeginReceive استفاده کنید. چون این متد ها برای مواقعی قرار داده شدن که دریافت ها نا هماهنگ باشن مثل پروژه خودتون که معلوم نیست چه موقع دیتا دریافت میشه.
تغییراتی که من دادم باعث میشه به همه کلاینت ها دسترسی داشته باشید و توی بازه زمانی 2 دقیقه اگه کلاینت دیتایی ارسال نکنه اونو حذفش میکنه. درضمن درصورت دیس شدنِ کلاینت تشخیص میده و بهتون اطلاع میده. کلاینت رو هم خودتون تغییر بدید و یه تایمر قرار بدید که در بازه زمانی کمتر از 2 دقیقه یه بایت ارسال کنه تا از دیسی شدن جلوگیری بشه :تشویق:

drawback
یک شنبه 11 آبان 1393, 18:26 عصر
سلام دوست عزیز
یکی از روش های برنامه نویسی شبکه بصورت آسنکرون میباشد که البته این روشم مشکلات خاص خودش رو داره اما یکی از خوبیهاش اینه که میتونید هر چندتا کلاینت رو به سرور وصل کنید و سرور آخ هم نمیگه من تست کردم 50 تا کلاینت از یه سیستم به برنامه سرورم وصل شد اطلاعات رو در sql ذخیره کرد و تا 1 ساعت که روشن بود هم هنگی وجود نداشت.
این کلاس برای گرفتن اطلاعات کلاینت


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Data;

namespace Server
{
public class seClient
{
public string ID
{
get;
private set;
}
public IPEndPoint EndPoint
{
get;
private set;
}

public Socket socket;
public Thread clientThread;

public seClient() //recieve data from each client indivisually
{
ID = Guid.NewGuid().ToString();
}

public seClient(Socket Accept)
{
this.socket = Accept;
ID = Guid.NewGuid().ToString();
EndPoint = (IPEndPoint)socket.RemoteEndPoint;

SendRegistrationPacket();
socket.BeginReceive(new byte[] { 0 }, 0, 0, 0, CallBack, null);

}
byte[] buffer;
void CallBack(IAsyncResult ar)
{
try
{
//Packet p = new Packet(PacketType.SendData,ID);
socket.EndReceive(ar);
buffer = new byte[socket.SendBufferSize];
int rec = socket.Receive(buffer);
if (rec < buffer.Length)
{
Array.Resize<byte>(ref buffer, rec);
}

if (Received != null)
{
Packet packet = new Packet(buffer);
Received(packet, this, buffer);
}
socket.BeginReceive(new byte[] { 0 }, 0, 0, 0, CallBack, null);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
Close();

if (Disconnected != null)
{
Disconnected(this);
}
}
}

public void Close()
{
socket.Close();
socket.Dispose();
}

public void SendRegistrationPacket()
{
Packet p = new Packet(PacketType.Registration, "server");
p.GData.Add(ID);
socket.Send(p.ToBytes());
}

public delegate void ClientReceivedHandler(Packet p,seClient sender, byte[] data);
public delegate void ClientDisconnectedHandler(seClient sender);

public event ClientReceivedHandler Received;
public event ClientDisconnectedHandler Disconnected;
}
}
و این کلاس برای معرفی کلاینت به سرور و سرور به کلاینت که بصورت DLL ساخته شده...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace Data
{
[Serializable]
public class Packet
{
public List<string> GData;
public int packetInt;
public bool packetBool;
public string senderID;
public PacketType packetType;

public Packet(PacketType type, string senderID)
{
GData = new List<string>();
this.senderID = senderID;
this.packetType = type;

}

public Packet(byte[] packetbytes)
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream(packetbytes);
if (ms.Length > 0)
{
Packet p = (Packet)bf.Deserialize(ms);
ms.Close();
this.GData = p.GData;
this.packetInt = p.packetInt;
this.packetBool = p.packetBool;
this.senderID = p.senderID;
this.packetType = p.packetType;
}

}
public byte[] ToBytes()
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, this);
byte[] bytes = ms.ToArray();
ms.Close();
return bytes;
}
}

public enum PacketType
{
Registration, Chat, SendData, Lock, Unlock, ShutDown, Restart, UsbAccept, Dissconnect
}
}

elyas_delshadnbe
شنبه 17 آبان 1393, 08:44 صبح
سلام کداتونو دیدم. تقریبا پروژه سرور رو بازنویسی کردم :لبخند: سعی کنید . . . .

دستتون درد نكنه واقعا .تشكر سايت برنامه نويس كمه. خيلي ممنونم ازتون واقعا

elyas_delshadnbe
شنبه 17 آبان 1393, 12:39 عصر
سلام دوست عزیز
یکی از روش های برنامه نویسی شبکه بصورت آسنکرون میباشد که البته این روشم مشکلات خاص خودش رو داره اما یکی از خوبیهاش اینه که میتونید هر چندتا کلاینت رو به سرور وصل کنید و سرور آخ هم نمیگه من تست . . .


خب شما تستتون رو با سيستم هاي مختلف انجام دادين؟مثلا 5 تا سيستم جدا براي كلاينت و 1 سيستم جا از اون 5 تا براي سرور؟
به نظرم نتايج متفاوت ميشه ها

elyas_delshadnbe
دوشنبه 19 آبان 1393, 08:35 صبح
سلام دوست عزیز
یکی از روش های برنامه نویسی شبکه بصورت آسنکرون میباشد که البته این روشم مشکلات خاص خودش رو داره اما یکی از خوبیهاش اینه که میتونید هر چندتا کلاینت رو به سرور وصل کنید و سرور آخ هم نمیگه من تست کردم 50 تا کلاینت از یه سیستم به برنامه سرورم وصل شد اطلاعات . . .


ممنون از شما

elyas_delshadnbe
پنج شنبه 22 آبان 1393, 13:22 عصر
اينم نسخه بعدي برنامه. با تشكر از pedram خان.فقط مشكل اينجاست كه كلاينتا رو اگه ببرم بالا بر خلاف انتظار حتي datalost هم دارم كه واسه Tcp خيلي عجيبه برام