برمجة - شبكات - كمبيوتر - منتديات الفريق العربي للبرمجة: كلاس الونسوك اللامتزامن Asynchronous Socket class - برمجة - شبكات - كمبيوتر - منتديات الفريق العربي للبرمجة

اذهب للمحتوى

صفحة 1 من 1
  • لا يمكنك بدء موضوع جديد
  • لا يمكنك الرد على هذا الموضوع

كلاس الونسوك اللامتزامن Asynchronous Socket class كلاس من برمجتي اضف تقييما للموضوع -----

#1     غير متواجد   راكان الحنيطي Icon

  • عضو مميز جدا
  • مجموعة المشرفين القدامى
  • مشاركات 1493
  • التقييم 0
  • النقاط المتوفرة 6.00
  • 0.00
    النقاط المحصلة
++

تم الارسال 10/08/2007 - 10:30 PM

السلام عليكم

اشارك معكم هذا الكلاس في إصدارة ال Beta Version :D و الذي قمت ببرمجته لكنه يحتاج الي بعض التعديل اللازم.

Asynchronous Sockets هي كلاسات موجودة في الدوت نت لعملية الإتصال بالشبكات اللامتزامنة بحيث يعمل البرنامج على إرسال و إستقبال المعلومات من و الي الشبكة بدون إيقاف البرنامج لإنتظار عملية الإرسال او الأستقبال(Synchronous Sockets).

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace ClientSocket
{
	class ClientSocket
	{

		#region Declarations
		Socket sckClient;
		String mHost;
		int mPort;
		

		public enum SocketState { Closed, Connecting, Connected }

		SocketState mState;

		#endregion

		#region Events
		public delegate void ConnectedHandler(Object Sender);
		public delegate void DisconnectedHandler(Object Sender);
		public delegate void DataReceivedHandler(Object Sender, String Text);
		public delegate void DataSendHandler(Object Sender);

		public event ConnectedHandler Connected;
		public event DisconnectedHandler Closed;
		public event DataReceivedHandler DataReceived;
		public event DataSendHandler DataSent;

		#endregion

		#region Helper Functions

		public IPAddress ResolveAddress(String host)
		{
			IPHostEntry iph = Dns.GetHostEntry(host);
			return iph.AddressList[0];
		}

		#endregion

		#region Properties
		public String Host
		{
			set
			{
				mHost = value;
			}
			get
			{
				return mHost;
			}
		}
		public int Port
		{
			set
			{
				mPort = value;
			}
			get
			{
				return mPort;
			}

		}
		public SocketState SockState
		{
			get
			{
				return mState;
			}
		}

		#endregion


		public ClientSocket()
		{
			//Create new Socket 
			sckClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
			mHost = "";
			mPort = 0;
			
			mState = SocketState.Closed;
		}

		#region Public functions
		public void Connect()
		{
			//Start connection
			if (mHost == String.Empty)
			{
				throw new ArgumentException("Host was not specified!");
			}
			else
			{
				try
				{
					EndPoint ep = new IPEndPoint(ResolveAddress(Host), mPort);

					sckClient.BeginConnect(ep, new AsyncCallback(ConnectedCallback), sckClient);

					mState = SocketState.Connecting;
				}
				catch (SocketException)
				{
					if (sckClient.Connected) mState = SocketState.Connected;
					else
					{
						mState = SocketState.Closed;
						Closed(this);
					}
				}

			}
		}
		public void Close()
		{
			if (sckClient != null && sckClient.Connected)
			{
				sckClient.Shutdown(SocketShutdown.Both);
				sckClient.Close();

				mState = SocketState.Closed;

				sckClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
				Closed(this);
			}
		}
		public void Send(String Data)
		{
			try
			{
				Byte[] buffer = Encoding.ASCII.GetBytes(Data);
				sckClient.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(DataSendCallback), sckClient);
			}
			catch (SocketException)
			{
				if (sckClient.Connected) mState = SocketState.Connected;
				else
				{
					mState = SocketState.Closed;
					Closed(this);
				}
			}
		}
		public void Send(Byte[] Buffer, int offset, int length)
		{
			try
			{
				sckClient.BeginSend(Buffer, offset, length, SocketFlags.None, new AsyncCallback(DataSendCallback), sckClient);
			}
			catch (SocketException)
			{
				if (sckClient.Connected) mState = SocketState.Connected;
				else
				{
					mState = SocketState.Closed;
					Closed(this);
				}
			}
		}
		#endregion
		#region Callbacks
		public void ConnectedCallback(IAsyncResult ar)
		{
			try
			{
				Socket s = (Socket)ar.AsyncState;
				s.EndConnect(ar);

				mState = SocketState.Connected;

				//Begin recevie
				StateObject sb = new StateObject();
				sb.ClientSocket = sckClient;
				s.BeginReceive(sb.Buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None, new AsyncCallback(DataReceiveCallback), sb);

				//Raise connection event
				
				Connected(this);
			}
			catch (SocketException)
			{
				if (sckClient.Connected) mState = SocketState.Connected;
				else
				{
					mState = SocketState.Closed;
					Closed(this);
				}
			}

		}
		public void DataReceiveCallback(IAsyncResult ar)
		{
			try
			{
				StateObject sb = (StateObject)ar.AsyncState;
				int BytesToRead = sb.ClientSocket.EndReceive(ar);

				String RecText = Encoding.ASCII.GetString(sb.Buffer, 0, BytesToRead);

				if (RecText.Trim() != String.Empty)
					DataReceived(this, RecText);

				//Begin recevie
				sb.ClientSocket.BeginReceive(sb.Buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None, new AsyncCallback(DataReceiveCallback), sb);
			}
			catch (SocketException)
			{
				if (sckClient.Connected) mState = SocketState.Connected;
				else
				{
					mState = SocketState.Closed;
					Closed(this);
				}
			}
		}
		public void DataSendCallback(IAsyncResult ar)
		{
			try
			{
				Socket s = (Socket)ar.AsyncState;
				s.EndSend(ar);
				DataSent(this);
			}
			catch (SocketException)
			{
				if (sckClient.Connected) mState = SocketState.Connected;
				else
				{
					mState = SocketState.Closed;
					Closed(this);
				}
			}
		}
		#endregion

	}
}


هذا الكلاس هو كلاس شبيه بأداة الونسوك و التي تقدم خدمات ال Event-Driven Network Programming و التي كانت اكثر من رائعة بصراحة, و اقدم لكم هذا الكلاس المتواضع و الشبيه بالأداة نوعا ما و الموجودة في الفجوال بيسك 6.0.

كيفية الإستخدام:

لتعريف المتغير من نوع هذا الكلاس تقوم بوضع الكود التالي:
ClientSocket cs;


و من ثم يجب علينا ان نقوم بعمل Initialize لهذا الObject كالتالي:
			cs = new ClientSocket();
			cs.Connected += new ClientSocket.ConnectedHandler(Connected);
			cs.Closed += new ClientSocket.DisconnectedHandler(onClose);
			cs.DataSent += new ClientSocket.DataSendHandler(DataSent);
			cs.DataReceived += new ClientSocket.DataReceivedHandler(DataReceived);

طبعا الكود الذي يلي سطر ال New هو كود لعملية ربط الأحداث بدالات قمنا بتعريفها لإستقبال المعلومات عن الConnection.
الأول يقوم بربط دالةConnected في الفورم الخاص بنا بالحدث Connected في السوكيت. و الثاني لإستقبال حدث ال Close لل Connection. اما الثالث و الرابع لعمليات أرسال البيانات و إستقبالها.

هذه هي تعريفات الدالات التي تستعدى عند قيام الحدث
void onClose(object sender)
		{
			MessageBox.Show("Connection closed");
		}

		void DataSent(object sender)
		{
			MessageBox.Show("Data sent");
		}

		void DataReceived(object sender, String RecText)
		{
			txtMsgs.Text += "Received\n";
			txtMsgs.Text += RecText;
		}
void Connected(object sender)
		{
			MessageBox.Show("Connected");
		}


و كود الزر للقيام بعملية البدء ال Connection
private void btnConnect_Click(object sender, EventArgs e)
		{
			cs.Host = txtHost.Text;
			cs.Port = Int32.Parse(txtPort.Text);
		 
			cs.Connect();
			
			
		}

حيث قمنا بأخذ قيم ال Host و Port من مربعات نصوص. و اعطيناها للكلاس ليقوم بعملية بدء الإتصال.

اما بالنسبة لإرسال رسالة
private void btnSend_Click(object sender, EventArgs e)
		{
			cs.Send(txtMsg.Text + "\n");
		}


طبعا الرجاء الإبلاغ عن الأخطاء عند إستخدام الكلاس و انا مستعد لأي سؤال.

طبعا يمكن إستخدام هذا الكلاس لتسهيل عملية عمل برامج المحادثة Client-Server وغيرها من برامج الشبكات



سوف اقوم بوضع كلاس ال ServerSocket قريبا أن شاء الله.

مع تمنياتي لكم بالتوفيق
راكان الحنيطي
0

شارك هذا الموضوع

      

#2     غير متواجد   إسماعيل الحلو Icon

  • عضو
  • مجموعة اعضاء
  • مشاركات 226
  • التقييم 0
  • النقاط المتوفرة 6.00
  • 0.00
    النقاط المحصلة
++

تم الارسال 10/08/2007 - 11:57 PM

ما شاء الله عليك
ألف شكر لك
0

#3     غير متواجد   بن العيد Icon

  • مشرف منتدى الأجهزة الكفية
  • مجموعة المشرفين القدامى
  • مشاركات 2385
  • التقييم 61
  • النقاط المتوفرة 14.00
  • 8.00
    النقاط المحصلة
++

تم الارسال 11/08/2007 - 07:07 PM

السلام عليكم

Quote

ما شاء الله عليك
ألف شكر لك

أخي إسماعيل هل جربت الكود؟؟

أخيMaverick شكرا على هذا الموضوع القيم ولكنك نسيت إضافة تعريف القسم StateObject
	public class StateObject
	   {
		   // Client socket.
		   public Socket ClientSocket = null;
		   // Size of receive buffer.
		   public const int BUFFER_SIZE = 256;
		   // Receive buffer.
		   public byte[] Buffer = new byte[BUFFER_SIZE];
		   // Received data string.
		   public StringBuilder sb = new StringBuilder();
	   }

كما نسيت أيضا بدأ التصنت ما إن كان هناك بيانات مرسلة من الطرف الآخر أم لا StartListening
بإمكانك الإعتماد على هذا الرابط

عند إستدعاء دالة غلق الربط بين الطرفين يجب غلقها فعليا ليس إرسال رسالة بذلك فقط
private void btn_Close_Click(object sender, EventArgs e)
	{ cs.Close();
	  MessageBox.Show("Connection Closed", "Close connection", MessageBoxButtons.OK, MessageBoxIcon.Information);
	}


...
0

#4     غير متواجد   راكان الحنيطي Icon

  • عضو مميز جدا
  • مجموعة المشرفين القدامى
  • مشاركات 1493
  • التقييم 0
  • النقاط المتوفرة 6.00
  • 0.00
    النقاط المحصلة
++

تم الارسال 11/08/2007 - 08:31 PM

السلام عليكم اخي و شكرا لك على مداخلتك.

http://msdn2.microso...y/bbx2eya8.aspx

بالنسبة لل StateObject فهو نفس الكلاس لكن بدون ال String Builer و انا كتبت الكلاس بناءا على tutorial قرأتها في ال MSDN بالإضافة الى إضافة اكواد لجعل الكلاس Event-Driven. بالنسبة لعملية الإغلاق الكود المرفق من قبلك يعتمد على الضغط على Button يستدعي كود الإغلاق بينما
void onClose(object sender)
		{
			MessageBox.Show("Connection closed");
		}

هي لجعل المبرمج قادرا على معرفة حدث قطع الإتصال حيث انه من الممكن ان يحصل خطأ يؤدي الى قطع الإتصال.

اما بالنسبة لعملية التنصت لإستقبال الإتصالات كسيرفر فقد ذكرت انه هذا كلاس منفصل :) و سأقوم بوضعه هنا عند الإنتهاء منه.

طبعا هذا جزء من مرحلتي لتعلم السي شارب و سأشارك بجميع الأكواد التي اكتبها و التي اتعلم من خلالها.

تم تعديل هذه المشاركة بواسطةMaverick: 11/08/2007 - 08:46 PM

0

#5     غير متواجد   راكان الحنيطي Icon

  • عضو مميز جدا
  • مجموعة المشرفين القدامى
  • مشاركات 1493
  • التقييم 0
  • النقاط المتوفرة 6.00
  • 0.00
    النقاط المحصلة
++

تم الارسال 11/08/2007 - 08:41 PM

تم تعديل الكود لبعض الأخطاء مع إضافة خاصية جديدة و هي معرفة حالة ال Socket
بحيث يمكن ان تكون
Closing, Closed, Connecting, Connected

cs.StateChanged += new ClientSocket.StateChangeHandler(StateChanged);
void StateChanged(object Sender)
		{
			this.Text = cs.SockState.ToString();
		}


الكود مرفق

ملف مرفق(ملفات)


0

#6     غير متواجد   أيمن منصور Icon

  • عضو جديد
  • مجموعة اعضاء جدد
  • مشاركات 42
  • التقييم 0
  • النقاط المتوفرة 9.00
  • 0.00
    النقاط المحصلة
++

تم الارسال 19/08/2008 - 01:12 PM

السلام عليكم :لقد استفدت لدرجة كبيرة من الكلاس الذي قمت بكتابته اخي راكان ولكن اذا اردت ان اعرف مصفوفة من هذا الكلاس فهل من الممكن ان تعطيني طريقة التعامل مع مصفوفة سوكيتات من حيث ارسال و استقبال البيانات لانه لدي جهاز يرسل و يستقبل بيانات عن طريق الشبكة ولقد نجح ارسال و استقبال البيانات من جهاز واحد ولكن المشكلة عندما يوجد اكثر من جهاز ارجو منك المساعدة
0

#7     غير متواجد   objectOrienteD Icon

  • عضو فعال
  • مجموعة اعضاء
  • مشاركات 324
  • التقييم 8
  • النقاط المتوفرة 6.00
  • 0.00
    النقاط المحصلة
++

تم الارسال 20/08/2008 - 08:27 AM

الف شكر اخ راكان ومشرفنا ابن العيد

الموضوع ده يفيدنى لو انا هاعمل ماسنجر لموقع معين مثلا اظن انى احتاج لشيئين
الـSocket Programming و الــ MultiThreading

فسؤالى الكلاس دى تفيدنى طبعا ما نبص فيها كويس ونغير فيها اللى يتماشى معانا

؟؟
0

شارك هذا الموضوع


صفحة 1 من 1
  • لا يمكنك بدء موضوع جديد
  • لا يمكنك الرد على هذا الموضوع

( 1 ) عضو يشاهد هذا الموضوع
( 0 ) الأعضاء, ( 1 ) الزوار, ( 0 ) عضو بدخول مخفي




لإفضل مشاهدة للمنتدى إستخدم مستعرض فايرفوكس
Free PageRank Checker

 الآن ... إستايل خاص لمن يملك هاتف iPhone  ... لتنزيل البرنامج  اضغط هنا