بخش اول : سوکت های همگام (سنکرون)
نویسنده : علیرضا شیرازی
منبع : http://shirazionline.net/system/content/view/25/9/
پیش نیاز : آشنایی با مفاهیم شبکه ای مانند IP و Port و Socket و Send - Receive و Client و Server
بخش اول : سوکت های همگام (سنکرون)
نویسنده : علیرضا شیرازی
منبع : http://shirazionline.net/system/content/view/25/9/
پیش نیاز : آشنایی با مفاهیم شبکه ای مانند IP و Port و Socket و Send - Receive و Client و Server
در مدل کلاینت - سرور ، مبادلات زیر بین کلاینت و سرور رخ میدهد
1- سرور سوکتی را تعریف میکند
2 - سرور سوکت را به یک IP که همان IP خودش است و یک پورت Bind میکند یا اختصاص میدهد
3-سرور به پورت گوش میدهد
4- کلاینت سوکتی را تعریف میکند و IP و پورت سرور را به آن اختصاص میدهد
5- کلاینت درخواست اتصال یا کانکت شدن به سرور را میدهد
6-سرور درخواست کلاینت را دریافت و آن را می پذیرد
7- کلاینت اطلاعاتی را ارسال می کند
8- سرور اطلاعات را می گیرد
9- سرور اطلاعات را ارسال میکند و کلاینت آن را میگیرد
10- سرور بسته میشود
11- کلانیت بسته میشود
شکل زیر این مراحل را نمایش می دهد :
ابتدا برنامه سمت سرور را مینویسم .
در این برنامه می بایست یک پورت را باز کرده و به آن گوش دهیم و دریافتی را نمایش دهیم .
ابتدا می بایست فضای نامهای زیر را با استقاده از using به کامپایلر سی شارپ معرفی کنیم :
System
System.Net
System.Net.Socket
System.Text
این کار را به این صورت انجام می دهیم :
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
اکنون متغیری به نام را به صورت سراسری و static تعریف میکنیم (از آنجایی که متد Main یک متد static است کلیه متغیرها و توابع مورد استفاده در آن نیز باید static باشند.)
متغیرها و متدهای Static را میتوان اینگونه تعریف کرد :
متغیرها و توابعی هستند که در یک کلاس به طور مشترک بین کلیه اشیاء گرفته شده از آن کلاس وجود دارند نه اینکه به ازای هر شیء یک نمونه از آن ایجاد شود. دسترسی به این متغیرها از طریق نام کلاس ممکن خواهد بود.
در مثال زیر کلاسی به نام Circle تعریف کرده ایم که دارای یک متغیر عادی به نام r است . این متغیر شعاع دایره را نگه میدارد.
متغیر PI به صورت static تعریف شده است چرا که عدد پی به ازای کلیه اشیاء این کلاس ثابت است.
در کلاس MainClass از کلاس Circle یک شیء ساخته ایم و از آن استفاده کرده ایم
class Circle
{
public static float PI =3.14;
public int r;
public static void PrintIt(double dbl)
{
Console.WriteLine(dbl);
}
}
class MainClass
{
static void Main(string[] args)
{
Circle cl = new Circle();
Console.WriteLine("Please Enter The Circle R");
cl.r = Convert.ToInt32( Console.ReadLine());
Circle.PrintIt(Circle.PI * cl.r * cl.r);
}
}
حال به مطلب اصلی خود بازگردیم :
یک شیء از کلاس سوکت به صورت سراسری و static ایجاد می کنیم :
static Socket sktListener;
در متد Main این سوکت را new مینکیم تا به آن حافظه اختصاص داده شود :
static void Main()
{
sktListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
AddressFamily.InterNetwork به معنای این است که از شبکه ای استفاده میکنیم که دارای IP نسخه 4 است.
SocketType.Stream برای سوکت هایی است که میخواهند به صورت Stream داده ها را تبادل کنند
ProtocolType.Tcp که نوع پروتکل ما را مشخص میکند.
اکنون می باید ِم آدرس IP و یک Port به سوکت مان اختصاص دهیم :
IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, 1800);
sktListener.Bind(ipLocal);
از آنجایی که این برنامه در سمت سرور اجرا میشود آدرس IP خاصی به آن نمیدهیم و پورت 1800 را باز میکنیم. کلاس IPEndPoint برای مشخص نمودن یک نود یا یک کامپیوتر در شبکه به کار میرود.
متد Bind نود مشخص شده را به سوکت اختصاص میدهد.
اکنون زمان گوش دادن به پورت است :
sktListener.Listen(100);
عدد 100 نشانه آن است که حداکثر 4 connection میتوانند در صف قرار گیرند .
اگر در این لحضه در command prompt دستور netstat –an را تایپ کنید میتوانید ببینید که پورت 1800 باز شده و در حال گوش دادن است.
حال میباید تقاضای کانکت شدن کلاینت را بپذیریم :
sktListener = sktListener.Accept();
حال برای گرفتن داده ها ، می بایست یک بافرتعریف نماییم .
نکته : در سوکت پروگرمینگ ، داده ها به صورت آرایه ای از بایت ها منتقل می شوند. برای ارسال رشته های یونیکد و .... بایست آنها را کد گذاری کنیم . برای کد گذاری و کد گشایی از کلاس System.Text و متدهای آن استفاده کنیم. مثلا دستور زیر رشته salam را با فرمت Ascii به آرایه ای از بایت ها تبدیل میکند
byte[] byt = Encoding.ASCII.GetBytes("salam");
و متد زیر آن را رمزگشایی میکند :
string str = Encoding.ASCII.GetString(byt);
ما عمل رمزنگاری را موقع ارسال داده ها و عمل رمز گشایی را موقع دریافت آنها انجام میدهیم .
اکنون میخواهیم داده ها را دریافت کرده و رمز گشایی کنیم :
byte[] buffer = new byte[500];
sktListener.Receive(buffer);
string Data = Encoding.ASCII.GetString(buffer);
حال میتوانیم داده ها را پردازش کنیم :
Console.WriteLine(Data);
سورس برنامه سمت سرور
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
static Socket sktListener;
static void Main(string[] args)
{
sktListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, 1800);
sktListener.Bind(ipLocal);
sktListener.Listen(100);
Console.WriteLine("Waiting For The Client");
sktListener = sktListener.Accept();
byte[] buffer = new byte[500];
sktListener.Receive(buffer);
Console.WriteLine("--- Client Sent This Message : ");
Console.WriteLine(Encoding.ASCII.GetString(buffer) );
sktListener.close();
}
خب ، ظاهرا توی این دو سالی که ما نبودیم این تاپیک خیلی گرد و خاک خورده! اگه دوستان مایل باشند از زیر گرد وخاک بکشیمش بیرون و کمی سر و سامونش بدیم!
چرا تاپیک به این خوبی استاپ خورد.؟؟
آره دوستان ممنون میشم ادامه بدید
چون منبع در این مورد خیلی کمه
salam
khaste nabashid
ma ghorbany hastam .
va taze dar morede Soket Programing shoro kardam vali Manba peida nakatdam .
Please Very Help
merci
سلام
ممنون
باز هم ادامه بدید
استاد ممنون میشم دوباره شروع کنید
عالیه تو رو خدا ادامه بدین که واقعا محتاج شدمتا آخر ترم باید پروژه رو تحویل بدم
ممنونم
اگه ایجاد کننده ی تاپیک اجازه بدن ، من میتونم مباحث رو ادامه بدم. البته اگه استقبال شه.
فکر میکنم یکی از دلایلی که این تاپیک استاپ شد عدم استقبال بود.
سلام خسته نباشید مطالبتون جالب بود اگه میشه ادامه بدید حتما کسانی که علاقه مند هستند سر میزنند
باتشکر ازآقای شیرازی
مطالب تاپیک اینقدر خواننده رو محو می کنند که از تشکر و اظهار نظر یادشون میره .
اگه امکانش هست ادامه بدید.
سلام
اگر کسی سوکت بلده بیاد و بنویسه
والله ثواب داره
سلام
من پروژه چت محلي دارم،اين برنامه سمت سرور خيلي خوبه اما نميدونم كجا بايد بنويسم آخه من سي شارپ كار نكردم خاهشا كمكم كنيد زمان زيادي ندارم . نياز به توضيحات پايه اي تر دارم
چرا كسي جوابگونيست من به اطلاعات بيشتري نياز دارم
خواهشا كمك كنيد
سلام
یه آموزش پیدا کردم که امیدوارم به دردتون بخوره
http://ehsanavr.com/wp-content/plugi...rogramming.rar
سلام اگه می شه این بحث رو ادامه بدید
خواهش می کنم
با تشکر از همه اساتید
اگه راست می گین سوکت پروگرمینگ توی دلفی رو توضیح بدین
منظورم آموزش کامل Indy
دو تا تابع وا سه دریافت و ارسال
تابع ارسال :
public static void Send(Socket socket, byte[] buffer, int offset, int size, int timeout) { int startTickCount = Environment.TickCount; int sent = 0; // how many bytes is already sent do { if (Environment.TickCount > startTickCount + timeout) throw new Exception("Timeout."); try { sent += socket.Send(buffer, offset + sent, size - sent, SocketFlags.None); } catch (SocketException ex) { if (ex.SocketErrorCode == SocketError.WouldBlock || ex.SocketErrorCode == SocketError.IOPending || ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable) { // socket buffer is probably full, wait and try again Thread.Sleep(30); } else throw ex; // any serious error occurr } } while (sent < size); }]
استفاده :
Socket socket = tcpClient.Client; string str = "Hello world!"; try { // sends the text with timeout 10s
Send(socket, Encoding.UTF8.GetBytes(str), 0, str.Length, 10000); } catch (Exception ex) { /* ... */ } ]
تابع دریافت :
public static void Receive(Socket socket, byte[] buffer, int offset, int size, int timeout) { int startTickCount = Environment.TickCount; int received = 0; // how many bytes is already received do { if (Environment.TickCount > startTickCount + timeout) throw new Exception("Timeout."); try { received += socket.Receive(buffer, offset + received, size - received, SocketFlags.None); } catch (SocketException ex) { if (ex.SocketErrorCode == SocketError.WouldBlock || ex.SocketErrorCode == SocketError.IOPending || ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable) { // socket buffer is probably empty, wait and try again Thread.Sleep(30); } else throw ex; // any serious error occurr } } while (received < size); }]
نحوه استفاده :
) { /* ... */ }
Socket socket = tcpClient.Client; byte[] buffer = new byte[12]; // length of the text "Hello world!" try { // receive data with timeout 10s
Receive(socket, buffer, 0, buffer.Length, 10000); string str = Encoding.UTF8.GetString(buffer, 0, buffer.Length); } catch (Exception ex