آموزش های این وب سایت به صورت رایگان در دسترس است. اطلاعات بیشتر
مشکل عدم دسترسی خریداران پیشین به برخی آموزش ها برطرف شد
بروز خطا
   [message]
اشتراک در سوال
رای ها
[dataList]

آموزش ارتباط کلاینت با سرور از طریق سوکت

AhmadVB  8 سال پیش  5 سال پیش
+57 0

یکی از دوستان یک سوال در مورد ارتباط با سرور از طریق سوکت مطرح کرده بود. در این تاپیک یک توضیح در مورد سوکت پروگرمینگ می دهم. امیدوارم بتونه به کسانی که نیاز دارند کمک کنه.

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

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

شما از این کلاس ها می توانید در برنامه های اندرویدی خود برای چت ، بازی های آنلاین چند نفره تحت شبکه داخلی یا تحت سرور ، یا دریافت Push Notification های اختصاصی خودتان به خوبی استفاده کنید. البته گفتم که سمت سرور را نیز با java نوشتم (که برای چت یا بازی های آنلاین درون شبکه محلی نیازی به تغییر آنها ندارید) ولی برای سمت سرور شما می توانید دستور معادل آن را در تمام زبانهای دیگر به راحتی پیدا کنید.

تمام کلاس ها دارای interface برای ایجاد ارتباط هستند. بدین شکل هر جای برنامه تان که یک شیء از آنها تعریف کردید می توانید listener های مربوط به متصل شدن ، قطع شدن ارتباط و دریافت اطلاعات را مدیریت کنید.

لطفا :

  • سوالات خود را زیر هر پست به صورت نظر ارسال کنید و پست نزنید.
  • اگر سوالی پرسیدید منتظر باشید تا جواب دهم. ممکن است هر روز فرصت نکنم به تاپیک سر بزنم.
  • ترجیحا به جای نوشتن تشکر از دکمه لایک استفاده کنید (چون فکر کنم اونقدر نظرات زیاد بشوند که کسی حوصله نکند همه را بخواند)
+3 0
سلام ، بنده گذرا نگاهی به مطالب تاپیک کردم ، بسیار جالب انگیز به نظر اومد ، خواستم جدای از لایک تاپیک ، بصورت کتبی هم تشکری از شما کرده باشم ، موفق باشید. (8 سال پیش)
0 0
سلام و با تشکر از شما.. بسیار تاپیک عالی و با ارزشی هست.. ممنون (8 سال پیش)
+1 0
سلام.ممنون از شما بابت آموزش خوب و ارزندتون. اگر بخاهیم چت داخل شبکه نباشه مثل برنامه واتساپ و تلگرام باید از چه طریقی ارتباط انجام بشه؟ (8 سال پیش)
0 0
ممنون میشم اگر کسی میدونه راهنمایی کنه (8 سال پیش)
+1 0
شما می تونید اون دو تا کلاسی را که من به عنوان سرور به زبان جاوا نوشتم را اگر برای سرور لینوکس بخواهید با پایتون یا c بنویسید یا برای سرور ویندوزی که می تونید راحت با #C بنویسید ( کد های C# خیلی شبیه به همین ها هست). (8 سال پیش)
 برای این سوال 6 پاسخ وجود دارد.
پاسخ به سوال 
AhmadVB  8 سال پیش
+12 0

سمت کلاینت
ابتدا سمت کلاینت را توضیح می دهم چون کمی ساده تر است.
خلاصه ی مطلب این است:

1- یک سوکت تعریف کنید:

 Socket socketToServer = new Socket();

2- سوکت را متصل کنید:

 socketToServer.connect(new InetSocketAddress(ServerIP,ServerPort),SOCKET_TIMEOUT);

3- ورودی و خروجی را مشخص کنید:

BufferedReader inputStream = new BufferedReader(new InputStreamReader(socketToServer.getInputStream(), "UTF-8"));
DataOutputStream outputStream = new DataOutputStream(socketToServer.getOutputStream());

4- اطلاعات مورد نظرتان را از ورودی دریافت و یا به خروجی ارسال کنید :

outputStream.write(outData.getBytes("UTF-8"));
inData = inputStream.readLine();

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

در زیر من یک کلاس به عنوان کلاینت تعریف کرده ام. این کلاس توسط یک Thread مدیریت می شود تا خللی در پردازش اصلی برنامه ایجاد نکند.

یک فایل جاوای جدید به نام  ClientSocket.java ایجاد کنید و اطلاعات زیر را داخل آن بریزید

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;

public class ClientSocket {
private Socket socketToServer;
private DataOutputStream outputStream;
private BufferedReader inputStream;
private int connectionStatus; //0= Disconnected , 1= Connected , 2= Connecting
private boolean loop;
Thread t;
private OnServerConnected mOnServerConnected;
private OnServerDisconnected mOnServerDisconnected;
private OnServerDataRecieve mOnServerDataRecieve;
String sIP;
String sPort;

public interface OnServerConnected {
void onConnect();
}

public interface OnServerDisconnected {
void onDisconnect();
}

public interface OnServerDataRecieve {
void onDataRecived(String Data);
}

public void setOnServerConnected(OnServerConnected eventListener) {
mOnServerConnected = eventListener;
}
public void setOnServerDisconnected(OnServerDisconnected eventListener) {
mOnServerDisconnected = eventListener;
}
public void setOnServerDataRecieve(OnServerDataRecieve eventListener) {
mOnServerDataRecieve = eventListener;
}

public ClientSocket(String serverIP, int serverPort ) {
sIP=serverIP;
sPort=serverPort;
}


public int getConnectionStatus() {
return connectionStatus;
}


public boolean isConnected() {
if (connectionStatus == 1)
return true;
else
return false;
}


public void connectToServer() {
if (t == null) {
t = new Thread() { // Read Data
@Override
public void run() {
loop = true;
while (loop) {
try {
connectionStatus = 2;
socketToServer = new Socket();
socketToServer.connect(new InetSocketAddress(sIP, sPort), 6000);
outputStream = new DataOutputStream(socketToServer.getOutputStream());
inputStream = new BufferedReader(new InputStreamReader(socketToServer.getInputStream(), "UTF-8"));
connectionStatus = 1;
if (mOnServerConnected != null)
mOnServerConnected.onConnect();
StartListen();
}
catch (Exception e) {
} finally {

if (connectionStatus == 1 && mOnServerDisconnected != null)
mOnServerDisconnected.onDisconnect();
connectionStatus = 0;
try {
if ( !socketToServer.isClosed())
socketToServer.close();
socketToServer = null;
outputStream = null;
inputStream = null;
}
catch (IOException e1) {
}
catch (Exception e1) {
}
try {
// waite for a few seccond to next try
Thread.sleep(10000);
}
catch (InterruptedException e) {
}
}
}
t = null;
}
};
t.start();
}
}
public void stop() {
loop = false;
try {
socketToServer.close();
}
catch (Exception e) {
}
}


public boolean sendMessage(String data) {
if (outputStream == null || connectionStatus != 1) {
return false;
}
try {
outputStream.write((data + "\n").getBytes("UTF-8"));
outputStream.flush();
}
catch (Exception e) {
try {
socketToServer.close();
}
catch (Exception e2) {

}
return false;
}
return true;
}


private void StartListen() {
while (true) {
if (socketToServer.isClosed()) {
connectionStatus = 0;
break;
}
String message = "";
try {
message = inputStream.readLine();
}
catch (IOException e1) {
}
if (message == null)
else if (message.length() == 0)
if ( !(message == null) && !message.equals("")) {
if (mOnServerDataRecieve != null)
mOnServerDataRecieve.onDataRecived(message);
}
else {
break;
}
}
}
}

0 0
سلام دوست عزیز ممنون از آموزش خیلی مفیدتون. ببخشید من متوجه نشدم که بدنه توابع اینترفیس چی هست و اونهارو کجا تعریف کردید؟! (8 سال پیش)
+2 0
دقیقا متوجه منظورتون نشدم ولی اینترفیس ها را در هر کلاس به صورت Public Interface درون خودش تعریف کرده ام. طریقه استفاده اش هم به این شکل هست که فرض کنیم شما یک جایی توی برنامه تان از کلاس ClientSocket یک شیء درست کرده اید به نام myClientSocket . مثلا برای فهمیدن رویداد وصل شدن این سوکت می توانید از دستور ...} myClientSocket.setOnServerConnected(new OnServerConnected استفاده کنید. و یا برای دریافت اطلاعات از دستور ...} myClientSocket.setOnServerDataRecieve(new OnServerDataRecieve استفاده کنید. به این شکل می توانید هر کاری را که می خواهید در زمان قطع و وصل شدن سوکت و یا دریافت اطلاعات از سرور انجام دهید. (8 سال پیش)
+1 0
متشکر از پاسختون. چیزی که من از اینترفیس ها متوجه شدم این هست که فقط سیکنچر توابع درون یک اینترفیس تعریف میشه و بدنه اش رو درکلاسی که میخاهیم ازش استفاده کنیم تعریف میکنیم. به عنوان مثال اینترفیس onServerConnected تابع onConnect() رو دربرداره! اما بدنه این تابع کجا impelement شده؟ در تابع connectToServer در بدنه if نوشتید که mOnServerConnected.onConnect() . تابع onConnect چه کاری انجام میده؟ و اون کار کجا تعریف شده؟ (8 سال پیش)
+3 0
مفهوم Interface این هست که فقط یک اسمه ! همونطور که متوجه شده اید بدنه ی از قبل تعریف شده ای نداره. کاربردش فقط واسه این هست که شما به کلاسهای دیگه ای که از شما یک شیء ساخته اند یک رویداد را اعلام کند و همین. اتفاق هایی که باید بیفتد را کسی که از شما یک شیء ساخته باید بنویسد ... (اگر دوست داشته باشد که اتفاقی بیفتد البته). (8 سال پیش)
0 0
متوجه شدم. سپاس از شما (8 سال پیش)
0 0
یکی از دوستان در خصوصی از من این سوال را پرسیده اند که : سلام خوبین .من اموزش سوکت نویسی سرچ کردم ولی همه لوکال بودن یعنی تحت یک شبکه .چه طوری میتونم با کاربرهای خارج از شبکه در ارتباط باشم یعنی سورس سرورم رو با ایپی ادرس دی ان اسم ست کنم .قبلا پورت فورواردینگ رو انجام داد (6 سال پیش)
0 0
پاسخ: در اونجایی که این دستور را صدا می زنید: socketToServer.connect(new InetSocketAddress(ServerIP,ServerPort),SOCKET_TIMEOUT); اگر دامنه دارید ، به جای ServerIP اسم دامنه یا همان DNS تان را هم می توانید ذکر کنید. اصلا هم نیازی به پورت فورواردینگ نیست. ولی اگر سرور تان با دامنه قابل دسترس نیست مبحث کمی تخصصی می وشد و باید ساختار شبکه بیشتر بررسی شود. (6 سال پیش)
پاسخ به سوال 
AhmadVB  8 سال پیش
+11 0

سمت سرور:
در این سمت هم مثل سمت کلاینت کافی است چیزی شبیه به سمت کلاینت اجرا کنید:

1- یک گیرنده (Listener) برای دریافت سوکت های ورودی تعریف کنید :

 ServerSocket server = new ServerSocket(PORT);

2- گیرنده را فعال کنید و پس از دریافت هر ارتباط ورودی آن را به یک سوکت باز تبدیل کنید:

 Socket socket = server.accept();

3- از اینجا به بعد مثل کلاینت ورودی و خروجی را مشخص کنید:

 BufferedReader inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());

4- اطلاعات مورد نظرتان را از ورودی دریافت و یا به خروجی ارسال کنید :

 outputStream.write((outData).getBytes("UTF-8"));
inData = inputStream.readLine();

حالا این وسط یک مشکلی وجود دارد که خیلی هم فنی است :
اگر لازم شد بیش از یک نفر به سرور وصل شود چه بکنیم ؟
این مشکلی است که کمی درک بیشتری از برنامه نویسی نیاز داریم تا بتوانیم آن را مدیریت کنیم.

من برای حل این موضوع از دو کلاس مجزا استفاده کرده ام. یک کلاس به عنوان مدیر جهت دریافت کانکشن ها و تبدیل آنها به سوکت و یک کلاس دیگر برای مدیریت اختصاصی هر کدام از سوکت های دریافتی !

+1 0
چطور میتونیم مطلع بشیم که پورت مورد نیاز ما از قبل بسته نشده ؟ اصطلاح پورت بسته ، کجا بکار برده میشه ؟ درواقع بسته بودن یک پورت زمانی اتفاق میوفته که در حال حاضر در استفاده هست ؟ و یا کلا بسته بودن پورت چیزی دیگه هست ؟ چه راهکاری میشه داد وقتی پورت توسط برنامه ایی دیگه در حال استفاده هست < معمولا زمانی که پورت از قبل در حال استفاده باشه ارتباط برقرار نمیشه < چطور میشه تشخیص داد این اختلال در ارتباط مشکلش از پورت بوده ؟ یا از نت ؟ (8 سال پیش)
+3 0
اصطلاح گوش کردن روی پورت یعنی اینکه نرم افزار شما به سیستم عامل اعلام می کند هر درخواستی به پورت مورد نظر آمد آن را به نرم افزار شما ارجاع دهد. به این ترتیب شما آن پورت را برای خود رجیستر کرده اید. حالا اگر قبل از شما نرم افزار دیگری این پورت را برای خود رجیستر کرده باشد طبیعتا زمانی که دستور ()server.accept را صدا می زنید با IOException مواجه می شوید. دقت کنید که گوش دادن به یک پورت هیچ ربطی به شبکه ندارد. ممکن است یک پورت حتی درون روتر شبکه شما فیلتر باشد ولی شما می توانید آن را رجیستر کنید. این موضوع صرفا مربوط به سیستم عامل است و شما نمی توانید مشکل باز یا بسته بودن پورت را در شبکه متوجه شوید. (8 سال پیش)
پاسخ به سوال 
AhmadVB  8 سال پیش
+10 0

کلاس زیر به عنوان یک مدیر کل کانکشن ها را دریافت می کند و به ازای هر دستگاه جدیدی که درخواست اتصال می کند یک شیء جدید از کلاس موبایل ( که قرار است هر کدام از سوکت های دریافتی را توسط آن مدیریت کنیم) ایجاد می کند.
من آن کلاس مربوط به کلاینت هایی که درخواست اتصال می دهند را Mobile و کلاس مدیر آنها را MobileManger نام گذاری کرده ام

import com.example.myserverapp.Mobile.OnMobileConnected;
import com.example.myserverapp.Mobile.OnMobileDataRecieve;
import com.example.myserverapp.Mobile.OnMobileDisconnected;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import android.app.IntentService;
import android.content.Intent;
import android.util.SparseArray;


public class MobileManager extends IntentService {

private SparseArray<Mobile> onlineMobiles = new SparseArray<Mobile>();
ServerSocket mobilesSocket = null;

public MobileManager(String name) {
super(name);
startServer();
}

public MobileManager() {
super("MobileManager");
startServer();
}

public void startServer(final int Port) {
new Thread(new Runnable() {
@Override
public void run() {
try {
mobilesSocket = new ServerSocket(Port);
while (true) {
Socket socket = mobilesSocket.accept();
Mobile mobile = new Mobile(socket);
mobile.setOnMobileConnected(new OnMobileConnected() {
@Override
public void onEvent(Mobile mobile) {
int mobileID = mobile.getMobileID();
if (onlineMobiles.indexOfKey(mobileID) > 0) {
onlineMobiles.remove(mobileID);
}
onlineMobiles.put(mobileID, mobile);
}
});
mobile.setOnMobileDisconnected(new OnMobileDisconnected() {

@Override
public void onEvent(Mobile mobile) {
int mobileID = mobile.getMobileID();
if (onlineMobiles.indexOfKey(mobileID) > 0) {
onlineMobiles.remove(mobileID);
}
}
});
mobile.setOnMobileDataRecieved(new OnMobileDataRecieve() {

@Override
public void onEvent(Mobile mobile, String data) {
// من در اینجا اطلاعات را برای پردازش به یک کلاس دیگر می فرستم
MessageParser.parseFromMobile(mobile.getMobileID(), data.trim());

}
});
mobile.startlisten();
}
}
catch (IOException e) {
} finally {
try {
mobilesSocket.close();
}
catch (Exception e) {
}
}
}
}).start();
}


public void disconnectAll() {
for (int i = 0; i < onlineMobiles.size(); i++)
onlineMobiles.get(onlineMobiles.keyAt(i)).disconnect();
}
public void disconnectMobile(int mobileID) {
if (onlineMobiles.indexOfKey(mobileID) >= 0)
onlineMobiles.get(mobileID).disconnect();
}

public void stopServer() {
disconnectAll();
try {
mobilesSocket.close();
}
catch (IOException e) {
}
}

public void sendData(String data, int MobileID) {
if (onlineMobiles.indexOfKey(MobileID) >= 0)
onlineMobiles.get(MobileID).sendToMobile(data);
}

@Override
protected void onHandleIntent(Intent workIntent) {

}

}

این کلاس به عنوان یک سرویس پیاده شده که بتوانید آن را در پس زمینه گوشی نیز اجرا کنید. در این حالت دیگر نیازی نیست برنامه باز باشد . (توضیحات مربوط به سرویس را در فیلم های استاد ببینید)

0 0
یه سوال ... اون سه تا کلاس کارش چیه و چجوری کدنویسی شده ؟؟ import com.example.myserverapp.Mobile.OnMobileConnected; import com.example.myserverapp.Mobile.OnMobileDataRecieve; import com.example.myserverapp.Mobile.OnMobileDisconnected; (8 سال پیش)
0 0
سلام. به جای com.example.myserverapp اسم پکیج خودتان را باید بگذارید (8 سال پیش)
0 0
اگر میشه سورس این آموزشی رو که دادید قرار بدید ... (8 سال پیش)
0 0
اینهایی که گذاشتم سورس بود ! عین کلاس هایی که خودم دارم استفاده می کنم. :) اگر منظورتون پروژه است... اون پروژه خیلی بزرگه ، حوصله جدا کردنشو ندارم :) ولی همین ها سورس کامل قسمت سوکش بود. (8 سال پیش)
0 0
سلام . ویدئو آموزشی سوکت نویسی که توسط مهندس آقاجانی ارائه شد کجاست ؟ تو پکیج نبود / (6 سال پیش)
0 0
startServer پارامتر ورودی شماره پورت میخواهد ، شما وارد نکرده اید ... چرا ؟ (6 سال پیش)
0 0
کلاس MessageParser رو کجا تعریف کردید ؟ (6 سال پیش)
پاسخ به سوال 
AhmadVB  8 سال پیش
+9 0

و هم اکنون نیز کلاس Mobile که وظیفه مدیریت هر کدام از سوکت های دریافتی را دارد.

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;


public class Mobile {

private int mobileID = 0;
private Socket socket;
private DataOutputStream outputStream;
private BufferedReader inputStream;
private int status = 0; // 0= disconnected 1= connected 2= Trying

private OnMobileConnected mOnMobileConnected;
private OnMobileDisconnected mOnMobileDisconnected;
private OnMobileDataRecieve mOnMobileDataRecieve;

public interface OnMobileConnected {
void onEvent(Mobile mobile);
}

public interface OnMobileDisconnected {
void onEvent(Mobile mobile);
}

public interface OnMobileDataRecieve {
void onEvent(Mobile mobile, String data);
}


public void setOnMobileConnected(OnMobileConnected eventListener) {
mOnMobileConnected = eventListener;
}
public void setOnMobileDisconnected(OnMobileDisconnected eventListener) {
mOnMobileDisconnected = eventListener;
}
public void setOnMobileDataRecieved(OnMobileDataRecieve eventListener) {
mOnMobileDataRecieve = eventListener;
}

public Mobile(Socket socket) {
this.socket = socket;
try {
outputStream = new DataOutputStream(socket.getOutputStream());
inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
status = 1;
}
catch (IOException e1) {
status = 2;
}
}

private void dataReciever(String data) {

if (mobileID == 0) {
try {
// من در اینجا فرض را بر این گذاشته ام که هر کلاینتی که متصل می شود
// اولین پیامی که ارسال می کند شماره آی دی اش باشد تا بتوانم بهتر آن
// دستگاه را مدیریت کنم.
JSONArray jArray = new JSONArray(data);
JSONObject jObject = jArray.getJSONObject(0);
int id = jObject.getInt("MobileID");
mobileID = id;
if (mOnMobileConnected != null)
mOnMobileConnected.onEvent(this);
}
catch (JSONException e) {
}
return;
}
//-----------------------------------------------------------------------------
if (mOnMobileDataRecieve != null)
mOnMobileDataRecieve.onEvent(this, data);
}


public boolean sendToMobile(String data) {
if (socket.isClosed()) {
return false;
}

try {
outputStream.write((data + "\n").getBytes("UTF-8"));
outputStream.flush();
}
catch (IOException e) {
return false;
}
return true;
}

public void startlisten() {
if (status == 1)
new Thread(new Runnable() {
@Override
public void run() {
listen();
onDisconnect();
}
}).start();
}

private void listen() {
while (true) {
try {
if (socket.isClosed()) {
status = 0;
return;
}
status = 1;
String data = "";
data = inputStream.readLine();
if ( !(data == null) && data.length() > 0) {
dataReciever(data);
}
else {
break;
}
}
catch (IOException e) {
return;
}
}
}

public void disconnect() {
try {
socket.close();
}
catch (IOException e) {
}
}

private void onDisconnect() {
try {
if (socket.isConnected())
socket.close();
}
catch (IOException e) {
}
if (mOnMobileDisconnected != null)
mOnMobileDisconnected.onEvent(this);
}
public int getStatus() {
return status;
}
public int getMobileID() {
return mobileID;
}
}

0 0
عالی موفق باشید (8 سال پیش)
0 0
عالی بود دوست عزیز ، میشه کل آموزش هاتون در قالب یک پروژه برای دانلود قرار بدید؟ (7 سال پیش)
0 0
سلام. این سورس بخشی از یک پروژه بزرگ بود که به عنوان تجربه در اختیار قرار دادم. انشاءالله اگر در آینده فرصتی بود شاید یک پروژه ایجاد کردم ولی فعلا فرصتش را ندارم. شاید سایر دوستان بتوانند از روی همین سورس ها یکی بسازند. (7 سال پیش)
0 0
برای ارسال فایل چه کاری باید انجام بدم؟آیا تلگرام هم برای چت از این طریق استفاده میکنه؟ (7 سال پیش)
0 0
برای ارسال فایل معمولا از کتابخانه های httpclient بهتره استفاده کنید. چون اگر از سوکت استفاده کنید ، سوکت به مدت طولانی مشغول میشه و باقی ارتباطاتتون مختل میشه. بله تلگرام هم برای چت از سوکت استفاده می کنه. (7 سال پیش)
پاسخ به سوال 
iman2420  6 سال پیش
0 0

سلام . ویدئو آموزشی سوکت نویسی که توسط مهندس آقاجانی ارائه شد کجاست ؟ تو پکیج نبود /

0 0
در بخش قدیمی آموزش های اندروید توسط اکلیپس هست (5 سال پیش)
پاسخ به سوال 
iman2420  6 سال پیش
0 0

کد های سمت سرور چطور میشه ؟ اصلا کد نیاز هست ؟ من VPS  لینوکسی دارم ، اون رو چطور پیکربندی کنم ؟


پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .