PDA

View Full Version : آموزش: ارسال و دریافت در برنامه نویسی سوکت



silsin
یک شنبه 10 خرداد 1394, 01:01 صبح
با سلام
توی این تاپیک می خوام چند تا مثال برنامه نویسی مربوط به این مبحث بزنم کارهایی مثل ارسال و دریافت پیغام - ارسال و دریافت فایل یا موزیک یا فیلم به وسیله برنامه نویسی سوکت

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

اولین برنامه (اتصال کلاینت سروری در برنامه نویسی سوکت )

کدهای کلاینت :
از tcp استفاده می کنیم

TcpClient client = new TcpClient();
private void button1_Click(object sender, EventArgs e)
{
client.BeginConnect("127.0.0.1",8080,new AsyncCallback(Connect_CallBack),client);
}

public void Connect_CallBack(IAsyncResult Result)
{

client.EndConnect(Result);
}


و کدهای سرور


TcpListener listener;
private void button1_Click(object sender, EventArgs e)
{
listener = new TcpListener(IPAddress.Any, 8080);
listener.Start();
listener.BeginAcceptTcpClient(new AsyncCallback(Accept_CallBack),listener);

}

public void Accept_CallBack(IAsyncResult Result)
{

listener.EndAcceptTcpClient(Result);
}





توی این کدها از قابلیت اسنکرونی استفاده شده که قضیه halt شدن برنامه اتفاق نیفته

sohrab08
یک شنبه 10 خرداد 1394, 12:53 عصر
یه مقدار کامل تر توضیح بدین:قلب:

silsin
چهارشنبه 13 خرداد 1394, 10:43 صبح
خب اینم اولین مثال این بخش
برنامه ای به وسیله Tcp که یک پیام رو به سمت سرور ارسال می کنه

TcpClient Virtual_Client;
TcpListener Server = new TcpListener(IPAddress.Any, 8080);
byte[] RecivedBuffer;

NetworkStream ServerStream;



private void button1_Click(object sender, EventArgs e)
{

Server.Start(100);
Server.BeginAcceptTcpClient(ServerAccept_CallBack, null);


}


void ServerAccept_CallBack(IAsyncResult Result)
{

Virtual_Client = Server.EndAcceptTcpClient(Result);
ServerStream = Virtual_Client.GetStream();
RecivedBuffer = new byte[4096];
ServerStream.BeginRead(RecivedBuffer, 0, RecivedBuffer.Length, ServerRead_CallBack, null);


}



void ServerRead_CallBack(IAsyncResult Result)
{
int ByteRecived = 0;
ByteRecived = ServerStream.EndRead(Result);
if (ByteRecived != 0)
{
SetText(ASCIIEncoding.ASCII.GetString(RecivedBuffe r));

RecivedBuffer = new byte[4096];
ServerStream.BeginRead(RecivedBuffer, 0, RecivedBuffer.Length, ServerRead_CallBack, null);
}



}

delegate void SetTextCallBack(string Text);
void SetText(string Text)
{
if (this.textBox1.InvokeRequired)
{
SetTextCallBack d = new SetTextCallBack(SetText);
this.Invoke(d, new object[] { Text });

}
else
{
this.textBox1.Text = Text;
}
}








سرور راه اندازی میشه و به ازای ورودی های کاربر شروع می کنه به خوندن ورودی های سوکت
دلیگیت هم به خاطر این تعریف شده چون مشکل thread safe رو حل کنه

کدهای بخش کلاینت :

TcpClient Client = new TcpClient();

;NetworkStream ClientStream
byte[] SendBuffer;

private void button2_Click(object sender, EventArgs e)
{
Client.BeginConnect("127.0.0.1",8080,Connect_CallBack,null);
}





private void button3_Click(object sender, EventArgs e)
{
if (Client.Connected)
{
SendBuffer = new byte[4096];
SendBuffer = ASCIIEncoding.ASCII.GetBytes(textBox2.Text);
ClientStream.BeginWrite(SendBuffer, 0, SendBuffer.Length, Send_CallBack, null);
}
else
{
MessageBox.Show("کلاینت هنوز راه اندازی نشده است");
}
}






void Connect_CallBack(IAsyncResult Result)
{
Client.EndConnect(Result);

ClientStream = Client.GetStream();


}

void Send_CallBack(IAsyncResult Result)
{
ClientStream.EndWrite(Result);
}



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


توضیح خط به خط

1- ابتدا کلانیت تعریف شده
2 - متغییر استریم برای انجام اعمال خواندن و یا نوشتن
3 - تعریف بافر ارسال
4- در کلید اول اتصال به سرور (به وسیله تکنیک اسنکرون )
5 - در کلید بعدی ارسال به سرور به وسیله تکنیک اسنکرون
و در ادامه متد های برگشتی مربوط به ارسال و اتصال ها

نکته :
برای ارسال پیغام ها چند تا بخش دیگه هم در نظر خواهیم گرفت که انشالله در پست های بعدی
بخش های مثل
ارسال با udp
ارسال با سوکت
همچنین یه تکنیک دیگه هم در رابطه با نحوه دریافت رو بررسی می کنیم

silsin
یک شنبه 17 خرداد 1394, 23:12 عصر
خب دومین بخش از مثال ها رو ادامه می دیم . اگه یادتون باشه قرار شد هر بخش رو قسمت بندی کنیم . بنابراین بهتره الان بگیم که دومین بخش از قسمت اول اموزش ارسال و دریافت در شبکه
توی دومین مثال می خواهیم نحوه ارسال و دریافت رو به وسیله تکنولوژی UDP بررسی کنیم .
پروژه جدیدی ایجاد کنید :
کدهای برنامه

کلاینت :

UdpClient udpClient = new UdpClient();
udpClient.Connect(tbHost.Text, 8080);
Byte[] sendBytes = Encoding.ASCII.GetBytes("Hello World?");
udpClient.Send(sendBytes, sendBytes.Length);


موارد مورد نیاز این بخش
یک Button , TextBox بوده که تکست باکس رو برای وارد کردن هاستی که می خواهیم به اون وصل بشیم استفاده می کنیم .
در خط سوم هم کلمه Hello World رو به سمت مقصد فرستادیم . به عنوان اولین پیام
توجه کنید که کلانیت ما تنها کاری که می کنه همینه !
حالا کدهای بخش سرور رو می نویسیم


public void serverThread()
{
UdpClient udpClient = new UdpClient(8080);
while(true)
{
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any,
0);
Byte[] receiveBytes = udpClient.Receive(ref
RemoteIpEndPoint);
string returnData = Encoding.ASCII.GetString(receiveBytes);
lbConnections.Items.Add(
RemoteIpEndPoint.Address.ToString() + ":" +
returnData.ToString()
);
}
}




private void Form1_Load(object sender, System.EventArgs e)
{
Thread thdUDPServer = new Thread(new
ThreadStart(serverThread));
thdUDPServer.Start();
}



تو بخش سرور ما از ترد برای دریافت استفاده کردیم . توی متدی که به عنوان متد اجرا شونده توسط ترد تعریف شده
ابتدا دریافت رو از سرور انجام می دیم .
و در دامه به وسیله تبدیلات ASCII اون رو به فرمت قابل خوندن تبدیل کرده و وارد کامپوننتی که می کنیم که می خوایم توی اون نمایش داده بشه (در اینجا ما از یک لیست استفاده کردیم )

اما دو خط بالایی :
در ابتدا یک نمونه از کلاس UDP تعریف شده که تنها کاری که می کنه اینه که به پورت اعلام شده گوش میده
یک حلقه While هم نوشتیم چون بتونه به طور دائم به قولی عمل گوش دادن به موارد دریافتی رو انجام بده توجه کنید اگه از while استفاده نکنید بعد از یک بار استفاده از ترد , ترد به صورت Stop در میاد

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

silsin
یک شنبه 17 خرداد 1394, 23:59 عصر
در قسمت اخر از بخش ارسال پیغام این روند رو به وسیله استفاده از کلاس سوکت بررسی می کنیم
کدهای بخش سرور :
در اینجا از یک Button به عنوان راه انداز سرور - از یک ListBox برای دریافت پیغام ها استفاده میک نیم

Socket Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Socket Virtual_Client;
IPEndPoint EndP = new IPEndPoint(IPAddress.Any, 8008);

Byte[] Recived;


private void button1_Click(object sender, EventArgs e)
{


Server.Bind((EndPoint)EndP);
Server.Listen(-1);
Server.BeginAccept(Server_BeginAccept, null);





}













void Server_BeginAccept(IAsyncResult Result)
{

Virtual_Client = Server.EndAccept(Result);
Recived = new Byte[Byte.MaxValue];
Virtual_Client.BeginReceive(Recived, 0, Recived.Length, SocketFlags.None, Server_BeginRecived, null);





}



void Server_BeginRecived(IAsyncResult Result)
{
int Recv = Virtual_Client.EndReceive(Result);

if (Recv > 0)
{
SetText(Encoding.ASCII.GetString(Recived));
Virtual_Client.BeginReceive(Recived, 0, Recived.Length, SocketFlags.None, Server_BeginRecived, null);




}




}

delegate void SetTextCallBack(string Text);




void SetText(String Text)
{

if (listBox1.InvokeRequired)
{

SetTextCallBack d = new SetTextCallBack(SetText);
this.Invoke(d, new object[] { Text });
}
else
{
listBox1.Items.Add(Text);
}


}







کدها رو یه بررسی می کنیم متناظر هر خط توضیحات رو می نویسیم
ابتدا یک نمونه از کلاس سوکت به همراه تنظمیات مورد نیازمون تعریف کردیم
نمونه دوم رو تعریف کردیم به خاطر دسترسی به کانکشن هایی که به سرور ما وصل میشن
مقدار Recived رو هم به عنوان بافر برای دریافت تعریف کردیم
همچنین به وسیله یک IPEndPoint مسیر اتصال رو تعیین کردیم

ابتدا به وسیله دکمه سرور شروع به گوش کردن به ادرس و پورت تعریف شده می کنه
و این کار رو تا نهایت رسیدن به مقداری که داخل متد Server.Listen تعریف کردیم ادامه میده
همچین بعد از این کار شروع به قبول در خواست های ورودی می کنه اینجا این کار رو به وسیله تعریف قابلیت اسنکرون انجام میدیم پس نیاز به متد بازگشتی هم داریم

در متد بازگشتی Server_AcceptCallBack مقدار اتمام قبول درخواست Server که برابر با یک سوکت هست رو به عنوان ورودی سوکت کلاینت مجازی خودمون قرار میدیم
بعد از این کار مستقیما از سوکت مجازی تعریف شده خودمون عمل خوندن رو شروع می کنیم اینبار هم به صورت اسنکرون

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

همچین دلیگیت SetText رو هم برای رفع مشکل Theread Safe که باعث میشه نتونیم در کلاکی همزان داخل لیست مقادیر رو وارد کنیم رو به کار بردیم


بخش کلاینت :
در اینجا از یک Button برای اتصال - یک Button دیگر برای ارسال پیغام - و یک TextBox هم برای نوشتن پیغام هایی که می خوایم ارسال کنیم


Socket Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Byte[] Send;




private void button2_Click(object sender, EventArgs e)
{

Client.BeginConnect(IPAddress.Parse("127.0.0.1"), 8008, Client_Connect_CallBack, null);



}







private void button3_Click(object sender, EventArgs e)
{

Send = new Byte[Byte.MaxValue];
Send = Encoding.ASCII.GetBytes(textBox1.Text);
Client.BeginSend(Send, 0, Send.Length,SocketFlags.None ,Client_Send_CallBack, null);
}





void Client_Connect_CallBack(IAsyncResult Result)
{

Client.EndConnect(Result);
}

void Client_Send_CallBack(IAsyncResult Result)
{
Client.EndSend(Result);

}
}


ابتدا سوکت کلانیت خودمون رو تعریف می کنیم
متغییر بایت رو هم برای بافر ارسال
در Button اول یک اتصال به سرور برقرار می کنیم
این اتصال به صورت اسنکرون اداره میشه بنابراین متد بازگشتی اون رو هم می نویسیم Client_Connect_CallBack
همچنین در Button بعدی هم روند ارسال رو تعریف می کنیم
(توجه کنید اینکه زیاد توضیح نمیدم به خاطر اینه که اول تاپیک هم گفتم اینجا می خوام مثال بزنم فقط . کمی توضیح رو برای این میدم تا کدها گنگ نباشن)

در بخش بعدی که اتفاقا مثل بخش اول سه قسمتیه روند ارسال یک فایل (فایل متنی - عکس - موزیک یا فیلم) رو بررسی می کنیم
با تشکر