برنامه نویسیسی شارپ

آموزش برنامه نویسی سوکت در #C

مجله اینترنتی آی تی پورت

به بیان ساده می توان گفت که سوکت به ترکیب یک آدرس ماشین ( IP ) و یک شماره درگاه ( Port ) گفته می شود. این دو با هم و بصورت مکمل هم در آدرس یابی تحت شبکه به برنامه های کاربردی کمک می کنند که هر برنامه تنها packet ارسالی خود را و تنها از آدرس مورد نظرش بدست آورد یا به عبارت دیگر علاوه به بحث رساندن بسته به کامپیوتر مقصد رساندن آن به برنامه کاربدی مربوطه نیز لازم است.

در مدل کلاینت – سرور ، مبادلات زیر بین کلاینت و سرور رخ می دهد:

  •  سرور سوکتی را تعریف میکند
  • سرور سوکت را به یک IP که همان IP خودش است و یک پورت Bind میکند یا اختصاص میدهد
  • سرور به پورت گوش میدهد
  • کلاینت سوکتی را تعریف میکند و IP و پورت سرور را به آن اختصاص میدهد
  • کلاینت درخواست اتصال یا کانکت شدن به سرور را میدهد
  • سرور درخواست کلاینت را دریافت و آن را می پذیرد
  • کلاینت اطلاعاتی را ارسال می کند
  • سرور اطلاعات را می گیرد
  • سرور اطلاعات را ارسال میکند و کلاینت آن را میگیرد
  • سرور بسته میشود ۱۱- کلانیت بسته میشود

برنامه سمت سرور

ابتدا برنامه سمت سرور را می نویسم. در این برنامه می بایست یک پورت را باز کرده و به آن گوش دهیم  و دریافتی را نمایش دهیم.

ابتدا می بایست فضای نامهای زیر را با استقاده از using  به کامپایلر سی شارپ معرفی کنیم:

using System;



using System.Net;



using System.Net.Sockets;



using System.Text;

اکنون متغیری به نام  را به صورت سراسری و static  تعریف می کنیم (از آنجایی که متد Mainیک متد static  است کلیه متغیرها و توابع مورد استفاده در آن نیز باید static باشند.)

 

 تعریف متغیرها و متدهای Static

متغیرها و  توابعی هستند که در یک کلاس به طور مشترک بین کلیه اشیاء گرفته شده از آن کلاس وجود دارند  نه اینکه به ازای هر شیء یک نمونه از آن ایجاد شود. دسترسی به این متغیرها از طریق نام کلاس ممکن خواهد بود.

یک شیء از کلاس سوکت به صورت سراسری و static ایجاد می کنیم :

staticSocket sktListener;

در متد Mainاین سوکت را new مینکیم تا به آن حافظه اختصاص داده شود:

staticvoid Main()



{



sktListener = newSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);



 

AddressFamily.InterNetwork به معنای این است که از شبکه ای استفاده می کنیم که دارای IP نسخه ۴ است.

SocketType.Stream برای سوکت هایی است که می خواهند به صورت Stream  داده ها را تبادل کنند.

ProtocolType.Tcp که نوع پروتکل ما را مشخص می کند.

اکنون می باید آدرس IP  و یک Port به سوکت مان اختصاص دهیم:

IPEndPoint ipLocal = newIPEndPoint(IPAddress.Any, 1800);



sktListener.Bind(ipLocal);

از آنجایی که این برنامه در سمت سرور اجرا میشود آدرس IP خاصی به آن نمیدهیم و پورت ۱۸۰۰ را باز می کنیم. کلاس IPEndPoint برای مشخص نمودن یک نود یا یک کامپیوتر در شبکه به کار میرود.

متد Bind  نود مشخص شده را به سوکت اختصاص می دهد.

اکنون زمان گوش دادن به پورت است:

sktListener.Listen(100);

عدد ۱۰۰ نشانه آن است که حداکثر ۴ connection میتوانند در صف قرار گیرند.

اگر در این لحضه در command prompt دستور netstat –an را تایپ کنید میتوانید ببینید که پورت ۱۸۰۰ باز شده و در حال گوش دادن است.

حال میباید تقاضای کانکت شدن کلاینت را بپذیریم:

sktListener = sktListener.Accept();

حال برای گرفتن داده ها، می بایست یک بافرتعریف نماییم.

نکته: در سوکت پروگرمینگ، داده ها به صورت آرایه ای از بایت ها منتقل می شوند. برای ارسال رشته های یونیکد و …. بایست آنها را کد گذاری کنیم. برای کد گذاری و کد گشایی از کلاس System.Text  و متدهای آن استفاده کنیم. مثلا دستور زیر رشته salam را با فرمت Ascii به آرایه ای از بایت ها تبدیل می کند.

byte[] byt = Encoding.ASCII.GetBytes("salam");

و متد زیر آن را رمزگشایی می کند:

string str = Encoding.ASCII.GetString(byt);

ما عمل رمزنگاری را موقع ارسال داده ها و عمل رمز گشایی را موقع دریافت آنها انجام میدهیم.

اکنون میخواهیم داده ها را دریافت کرده و رمز گشایی کنیم:

byte[] buffer = newbyte[500];



sktListener.Receive(buffer);



string Data = Encoding.ASCII.GetString(buffer);

حال می توانیم داده ها را پردازش کنیم.

 

سورس کامل برنامه سمت سرور

using System;



using System.Net;



using System.Net.Sockets;



using System.Text;



 



staticSocket sktListener;



staticvoid Main(string[] args)



{



sktListener = newSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);



IPEndPoint ipLocal = newIPEndPoint(IPAddress.Any, 1800);



sktListener.Bind(ipLocal);



sktListener.Listen(100);



sktListener = sktListener.Accept();



byte[] buffer = newbyte[500];



sktListener.Receive(buffer);



sktListener.close();



}



کدهایی که تا به اینجا دیدیم برای ایجاد سوکت های همگام یا سنکرون بوده است. این سوکت ها در برنامه های ویندوز و کلا سیستم های مالتی تسک کاربردی ندارند. چرا که بالفرض در زمانی از متد accept استفاده نموده ایم، در این حالت برنامه تا رسیدن یک سوکت به آن قفل شده و قادر به انجام کاری نیست.

 

برنامه سمت کلاینت

ایتدا یک سوکت تعریف می کنیم.

Socket sktClient = newSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

حال سرور را به آن معرفی می نماییم  و به آن کانکت می شویم:

sktClient.Connect("127.0.0.1", 1800);

اگر دوباره دستور netstat –an را در Command prompt  تایپ کنیم می بینیم که ارتباظ برقرار شده است. به شماره پورتها در آن دقت کنید.

اکنون داده های ارسالی را آماده می کنیم:

string str = "Hello Server....";



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

داده ها را ارسال می کنیم:

sktClient.Send(buffer);

و سوکت را میبندیم :

sktClient.Close();

 

سورس کامل برنامه سمت کلاینت

using System;



using System.Net;



using System.Net.Sockets;



using System.Text;



 



staticvoid Main(string[] args)



{



Socket sktClient = newSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);



sktClient.Connect("127.0.0.1", 1800);



string str = "Hello Server....";



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



sktClient.Send(buffer);



sktClient.Close();



}



 

یک نمونه دیگر از سورس برنامه سوکت پروگرمینگ

سورس سرور:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.Net;

using System.Net.Sockets;





namespace Server1

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

        static Socket ServerSock;

        private void Form1_Load(object sender, EventArgs e)

        {

            ServerSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IPEndPoint SockAdd = new IPEndPoint(IPAddress.Any, 1050);

            ServerSock.Bind(SockAdd);

            ServerSock.Listen(100);

            ServerSock = ServerSock.Accept();

        }



        private void button1_Click(object sender, EventArgs e)

        {

            try

            {

                NetworkStream Serverstream = new NetworkStream(ServerSock);

                byte[] buffer2 = new byte[100];

                ServerSock.Receive(buffer2);

                string Data = Encoding.ASCII.GetString(buffer2);

                listBox1.Items.Add("Maryam: "+Data);

                Serverstream.Flush();



            }

            catch (Exception ex)

            {

                MessageBox.Show(ex.ToString());

            }

        }



        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)

        {

            if (e.KeyChar == (char)Keys.Enter)

            {

                NetworkStream Serverstream = new NetworkStream(ServerSock);

                byte[] buffer3 = new byte[100];

                buffer3 = System.Text.Encoding.ASCII.GetBytes(textBox1.Text);

                ServerSock.Send(buffer3);

                Serverstream.Flush();

                listBox1.Items.Add("Me: " + textBox1.Text);

                textBox1.Clear();

            }

        }



    }

}





 

سورس کلاینت:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.Net;

using System.Net.Sockets;



namespace Client

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

        static Socket ClientSock;

        private void Form1_Load(object sender, EventArgs e)

        {

            ClientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            ClientSock.Connect("127.0.0.1", 1050);



        }



        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)

        {

            if (e.KeyChar == (char)Keys.Enter)

            {

                NetworkStream Clientstream = new NetworkStream(ClientSock);

                byte[] buffer1 = System.Text.Encoding.ASCII.GetBytes(textBox1.Text);

                ClientSock.Send(buffer1);

                Clientstream.Flush();

                listBox1.Items.Add("Me: "+ textBox1.Text);

                textBox1.Clear();

            }

        }



        private void button1_Click(object sender, EventArgs e)

        {

            byte [] buffer= new byte [100];

            NetworkStream Clientstream=new NetworkStream (ClientSock );

            ClientSock.Receive(buffer);

            string Data = Encoding.ASCII.GetString(buffer);

            listBox1.Items.Add("Server: "+ Data);

            Clientstream.Flush();



        }

    }

}

با تشکر از جناب سعید جعفری

گفتگو ها
    محمد

    تشکر بابت آموزش جناب جاهدی

    hafez

    سلام.خیلی ممنون بابت توضیحاتتون.

    من دوتا کد آخرتون رو که برای سرور و کلاینت هست توی دو تا پروژه جداسی شارپ کپی کردم.

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

    معصومه بهرامی

    با سلام

    من بک برنامه Socket نوشتم

    مشکلی که من دارم این است که زمانی که Client به صورت ناگهانی قطع میشود(قطع شدن کابل و یا قطع شدن سیستم) سمت Server متوجه قطع شدن Client نمی شود و همچنان Client به صورت Connect باقی میماند.

    از شما تقاضا دارم در صورت امکان اینجانب را راهنمایی نمایید.

    با تشکر

    محمد

    ممنون از مطالب مفیدتان

    داخل این لینک یک فیلم خوب سوکت هم وجود داره من دیدم خوب بود

    http://www.aparat.com/v/d1bnZ

    sepide

    خیلی سایت خوب و مفیدی بود خیلی کمکم کرد ممنون

    عالییییییییییییییییی بود

    فاطمه

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

    سلام میشه اینو پی دی اف کنید توروخدا خیلی به دردم میخوره

    واژه رمزنگاری صیح نمی باشد.

    در اینجا شما کد گذاری می کنید که زمین تا آسمان بارمز نگاری متفاوت است.

    محمد

    خیلی خوب بود، سپاس.

    بسیار عالی بود ممنون

    محمد

    سلام تشکر بسیار عالی بود

    یک منبع دیگه پیدا کردم در این لینک برای دوستان قرار دادم

    http://s5.picofile.com/file/8153780042/Class4.rar.html

    محمدعلی

    سلام ببخشید

    من میخوام یه برنامه ساده آندروید بسازمم باید چه بخش هایی رو یاد بگیرم ؟

    میشه ایمیل کنید لینک رو

    خیلی سپاس گذارم

      سلام
      شما برای یادگیری برنامه نویسی اندروید بهتر هست از این سایت استفاده کنید.
      http://androidcode.ir
      در حال حاضر در آی تی پورت آموزش برنامه نویسی اندروید داده نشده
      موفق باشید.

    ناشناس

    سلام

    من با Asp.net یک برنامه کلاینت سرور نوشتم که کاربر از طریق ای پی برای سرور دیتا ارسال میکنه . این برنامه در محیط کامپیوتر خودم و با ای پی استاتیک درست کار میکنه . اما وقتی برنامه رو روی هاست که دارای ای پی اختصاصی است قرار میدم برنامه خطا میده .

    خطای سمت کلاینت : System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 212.83.185.60:9889

    at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)

    at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)

    می خواستم ببینم مشکل از تنظیمات هاسته یا از برنامه نویسی .

    با تشکر

    حسن

    سلام

    من با Asp.net یک برنامه کلاینت سرور نوشتم که کاربر از طریق ای پی برای سرور دیتا ارسال میکنه . این برنامه در محیط کامپیوتر خودم و با ای پی استاتیک درست کار میکنه . اما وقتی برنامه رو روی این هاست که دارای ای پی اختصاصی است قرار میدم برنامه خطا میده .

    خطای سمت کلاینت : System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 212.83.185.60:9889

    at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)

    at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)

    می خواستم ببینم مشکل از تنظیمات هاسته یا از برنامه نویسی .

    الیزه

    ممنونم

    sobhan mozfari

    با سلام و خسته نباشید

    من چند مدته زدم تو ار سوکت همه فیلم اموزشی هارو هم دیدم و کامل یاد گرفته ام و لی هنوز اون طوری ک خودم میخوام نیستم .منبع خیلی کمه و نتونسم منبعی پیدا کنم اگر کتاب چاپ شده چیزی سراغ دارید لطفا ان را بران ایمیل کنید ممنون

    سپاس

    سلام خیلی ممنون بابت سایت خوبتون…

    ﻣﺼﻂﻔﻲ

    ﻣﺘﺸﻜﺮ ﺑﺎﺑﺖ ﺁﻣﻮﺯﺵ

    مهشید

    ممنونم از آموزشتون

    اما من یکی با نحو اجرای این کدها مشکل دارم . واقعا ممنون می شم نحو اجرا هم توضیح بدید

    negin

    سلام،ممنون از اموزشتون این برنامه را بدون خطا Trace کردم ولی در ادامه کار مشکل برخوردم :که بعد از برقراری ارتباط client با سرور با توجه به بازه ای که سرور قرار میدهد عددی را وارد نمایید چنانکه این عدد با عدد انتخابی سرور برابر بود پیغام win چنانچه کوچکتر بود small چنانچه بزرگتر بودbig اعلام شود و کاربر عدد دیگری وارد کند این عملیات ١٠ بار انجام شود چنانچه کاربر نتوانست عدد انتخابی را وارد کند با you failed مواجهه شود و ارتباط قطع شود نکته. امکان اتصال چندین کلاینت بصورت همزمان فراهم شود و سرور برای هر کلاینت بازه متفاوتی را در نظر میگیرد. ممنون

    میشم راهنماییم کنید

    محمد آرمان

    سلام من میخوام برای یک بازی تحت شبکه موبایل که با وای فای انجام میگییره برنامه بنویسم آیا با این آموزشی که شما گذاشتین میتونم این کارو بکنم ؟

    سرویس و نگهداری آسانسور

    سلام .دوره حضوریه م برای برنامه نویسی سوکت دارید آیا؟

    C

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

    دمتون گرم تحقیق دانشگاه رو راحت انجام دادم