آموزش Socket در برنامه نویسی اندروید بخش دوم
سلام دوستان در این سری از آموزش های برنامه نویسی اندروید به آموزش Socket در برنامه نویسی اندروید بخش دوم می پردازیم در مطلب قبلی خیلی از دوستان اشاره کردن که برنامه به درستی کار نمی کند با بررسی که انجام دادم متوجه شدم در بیشتر مودم ها این قابلیت وجود ندارد به همین منظور امروز پست آموزشی دیگری را در همین رابطه ایجاد کردیم در ادامه با ما همراه باشید.
در این بار ما دو تا اپلیکیشن جدا درست می کنیم کی یکی از آنها سرور و دیگری Client می باشد و باید بروی دو گوشی یا Emulator اجرا شود البته دقت کنید که باید به یک مودم وصل شوند یا یکی از گوشی ها Hotspot شود و گوشی دیگری به آن وصل شود و در هر صورت باید یک آیپی وصل شده باشند.
قبل از هرچیز وارد فایل AndroidManifest.xml شده دسترسی های زیر را اضافه کنید.
1 2 | <uses-permission android:name="android.permission.INTERNET" > </uses-permission> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" ></uses-permission> |
حالا می خواهیم بخش سرور را پیاده سازی کنیم.
در بخش activity_main.xml کد های زیر را قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/text2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" > </TextView> </LinearLayout> |
همانطور که میبینید فقط شامل یک textView می باشد چون فقط در بخش سرور می خواهیم پیام رو از Client دریافت کنیم.
سپس یک فایل به نام Server.java ایجاد کنید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | package ir.programchi; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.widget.TextView; public class Server extends Activity { private ServerSocket serverSocket; Handler updateConversationHandler; Thread serverThread = null; private TextView text; public static final int SERVERPORT = 6000; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text = (TextView) findViewById(R.id.text2); updateConversationHandler = new Handler(); this.serverThread = new Thread(new ServerThread()); this.serverThread.start(); } @Override protected void onStop() { super.onStop(); try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } class ServerThread implements Runnable { public void run() { Socket socket = null; try { serverSocket = new ServerSocket(SERVERPORT); } catch (IOException e) { e.printStackTrace(); } while (!Thread.currentThread().isInterrupted()) { try { socket = serverSocket.accept(); CommunicationThread commThread = new CommunicationThread(socket); new Thread(commThread).start(); } catch (IOException e) { e.printStackTrace(); } } } } class CommunicationThread implements Runnable { private Socket clientSocket; private BufferedReader input; public CommunicationThread(Socket clientSocket) { this.clientSocket = clientSocket; try { this.input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream())); } catch (IOException e) { e.printStackTrace(); } } public void run() { while (!Thread.currentThread().isInterrupted()) { try { String read = input.readLine(); updateConversationHandler.post(new updateUIThread(read)); } catch (IOException e) { e.printStackTrace(); } } } } class updateUIThread implements Runnable { private String msg; public updateUIThread(String str) { this.msg = str; } @Override public void run() { text.setText(text.getText().toString()+"Client Says: "+ msg + "\n"); } } } |
در بالا ما از serverSocket استفاده کردیم serverSocket برای ارتباط های Tcp و Udp استفاده می شود و به یک پورت گوش میدهد (listen) یعنی پس به صورت معمول ما نیاز به آیپی نداریم و فقط کافی است به یک آیپی وصل شده باشیم خودش آیپی ادرس را به دست می آورد و در بالا ما از پورت 6000 استفاده کردیم شما باید این پورت را باز کنید در ادامه نحوه باز کردن این پورت را به شما آموزش می دهیم البته دقت کنید کار کردن بروی پورت Emualtor کمی فرق دارد در ادامه توضیح خواهم داد.
حالا زمان این است اپلیکیشن دوم خودمان را که Client باشد ایجاد کنیم.
دسترسی های مانند قبل است پس آنها را اضافه کنید.
یک فایل به نام activity_main.xml ایجاد کرده کدهای زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <EditText android:id="@+id/EditText01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="JavaCodeGeeks" > </EditText> <Button android:id="@+id/myButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="onClick" android:text="send !" > </Button> </LinearLayout> |
شامل یک EditText برای دریافت ورودی از کاربر و یک دکمه برای ارسال داده است.
حالا یک فایل به نام Client.java ایجاد کرده و کد های زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | package ir.programchi; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.EditText; public class Client extends Activity { private Socket socket; private static final int SERVERPORT = 5000; private static final String SERVER_IP = "10.0.2.2"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread(new ClientThread()).start(); } public void onClick(View view) { try { EditText et = (EditText) findViewById(R.id.EditText01); String str = et.getText().toString(); PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())), true); out.println(str); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } class ClientThread implements Runnable { @Override public void run() { try { InetAddress serverAddr = InetAddress.getByName(SERVER_IP); socket = new Socket(serverAddr, SERVERPORT); } catch (UnknownHostException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } } } } |
در بالا اگر دقت کنید شماره port فرق می کند ! علت آن به خاطر این است که وقتی شما دو emualtor بروی یک pc اجرا می کنید هر Emulator به یک آیپی آدرس و پورت مشخص متصل می شود حالا چاره کا را باید اینطور که توضیح میدهم حل کنید در بالا نباید SERVER_IP اگر می خواهید در emulator اندروید استودیو استفاده کنید تغییر دهید این آیپی پیشفرض مجازی ساز اندروید استودیو است !
ابتدا برنامه اول را بروی Emulator اجرا کنید منظورم server است حالا cmd را باز کنید وارد پوشه adb شوید به صورت معمول در ریشه زیر نصب می شود.
1 | C:\Users\نام کاربری شما\AppData\Local\Android\sdk\platform-tools |
و در cmd کد زیر را قرار دهید.
1 | cd C:\Users\نام کاربری شما\AppData\Local\Android\sdk\platform-tools |
Enter را بزنید حالا کد زیر را اجرا کنید
1 | adb devices |
برای شما یک شماره پورت می نویسد port می نویسد حالا باید آن پورت را بر دارید و به بخش کد Server.java رفته و در قسمت SERVERPORT آن را وارد کنید این می شود پورت سرور شما حالا این Emualtor را نبندید برنامه دوم را در یک Emulator دیگه اجرا کنید سپس دوباره وارد دستور adb devices را اجرا کنید هم اکنون دو پورت به شما نمایش داده می شود پورت دومی را برداشته و وارد Client.java شده و در SERVERPORT قرار دهید حالا زمان redirect کردن یا PortForwarding است .
حالا در همان مسیری که هستید کد زیر را اجرا کنید. (در صورتی که با خطا مواجه شدید باید از قسمت programs and features باید Telent را فعال کنید به صورت معمول در بیشتر ویندوز ها این قابلیت خاموش است اگر نتونستید فعالش کنید در اینترنت یک سرچی بزنید)
1 | telnet localhost 5554 |
Enter را زده اگر پیغام خطا مواجه شدید پورت را به 5037 تغییر دهید.
1 | redir add tcp:5000:6000 |
در اینجا پورت 5000 را به 6000 redirect کردیم شما باید دو پورتی را که به دست آوردید در اینجا قرار دهید
تست برنامه !
حالا دوستانی که می خواهند روی دو گوشی تست کنن ! باید port Forwarding انجام دهند و پورت ها را در دو جا یکی قرار دهند.
این آموزش هم پایان رسید.
موفق و موید باشید.
فکر کنم کدها ناقصن
ادیت تکست وجود نداره حتی تو کلاینت به نبود ادیت تکست گیر میده فکر کنم کدهای اکتیویتی مین رو هم بزارین بهتره
سلام لطفا دوباره بررسی کنید کد ها مشکل ندارن ! مشکل در copy و Past شما ست دوباره بررسی کنید !
موفق و موید باشید.
کدها درستن اقا امید اون قسمت کدم هست دقت کنی
اقای جعفری پور میشه پروژه رو پیوست کنین ایمپرت کنیم .منم یک مشکلی دارم میدونم از خودمه
به زودی قرار می دهیم
خیلی جالبه.مهندس با این نوع کد نویسی میشه یک مسنجر شخصی ساخت؟
لطفا اموزشهای جالب این سایت رو هم بزارین اینجا عالین
چشم قرار می دهیم.
بحث سوکت نویسی کمی عجیبه همیشه یه مشکلی پیش میاد فقط چند نرم افزار میشناسم درست کار میکنن مثلا تیم ویور برای اندروید
استاد یک نرم افزار دیدم میتونه ریموت دسکتاپ کنه کجا میشه اموزشش رو پیدا کرد یعنی میشه صفحه گوشی رو از یک گوشی دیگه دید مثل مال ویندوز
بخش سوکت نویسی complexity فوق العاده بالایی داره و بزرگترین برنامه نویس های جهان هم هنوز با این بخش به کلی مشکل می خورند فقط کافیه یک بخش را کمی اشتباه بنویسید کل برنامه کار نخواهد کرد برنامه های زیادی هستند که این کار را انجام میدهند البته باگ های زیادی دارند این طور که بررسی کردم پیاده سازی چیزی که شما می خواهید کمی سختر از کار با Socket است اما راهی برای استفاده از آن وجود دارد شما می توانید از Guacamole استفاده کنید این سرویس این امکان رو به شما میده تا یک Remote Desktop به صورت Html5 بروی webview ایجاد کنید.
موفق و موید باشید.
سلام
یک سوال داشتم؟
من قسمت کد کلاینت را پیاده کردم و درست رشته ارسال کردم حالا می خوام متن ارسالی از سرور رو دریافت کنم و نمایش بدهم چیکار باید بکنم؟؟
یعنی در کنار کد مربوط به کلاینت بالا چی باید اضافه کنم؟؟؟
و انکه می خوام وقتی ارتباط tcp قطع شد با یک toast بفهمم چیکار باید بکنم لطفا راهنمایی کیند؟؟؟
سلام قربان وقتتون بخیر.
پوزش میطلبم. بنده تمامی کار هایی که فوق ذکر کردید را انجام دادم اما متاسفانه کد ها کار نکرد.
البته چون بنده می خواستم نرم افزار ها را بر روی دو گوشی چک کنم هر دو پورت را 6000 قرار دادم.
لازم به ذکر هست که بنده با استفاده از دستور telnet پورت ها را بررسی کردم اما انگار بسته هستند و هرچی میگردم چیزی متوجه نمیشم که چه طوری می تونم این پورت را باز کنم.
ممنون میشم راهنمایی ام کنید.
باسپاس فراوان.
سلام در مورد باز کردن port گوشی اطلاعی ندارم و شاید نیازمند روت بودن گوشی باشد چون اگر به همین راحتی بتوان پورت باز کرد گوشی به راحتی توسط برنامه های جانبی نفوذ پذیر میشوند و شاید باید با دستورات super user کار کنید برای اینکار شما باید به مودم وصل شید و port رو باز کنید و به صورت ptp گوشی ها رو بهم متصل کنید.
موفق باشید.
باسپاس فراوان از شما برای پاسخگوئیتان.
خب مثلا نرم افزاری مثل تلگرام چه جوی کار میکنه؟ مگه اون هم از سوکت بهره نمی بره؟(البته به غیر از اینکه اون آی پی اختصاصی داره و دیتا ها را به سمت سرور میفرسته)
سلام به همین شکل است پورت سرور با پورت گوشی خیلی متفاوت است.
درود
ضمن قدر دانی از زحماتتون،امکانش هست که توی هاست شخصی سی پنل با استفاده از دستورات پی اچ پی میزبانی برای اتصال دستگاه ها فراهم کنیم؟
اگر پاسختون مثبته لطفا بفرمایید از کجا باید شروع کرد و با چه عناوینی دنبالش بگردم.
سلام و دورد
چیزی که می فرمایید رو میشه به شکل یک rest api پیاده سازی کرد در رابطه با اتصال مستقیم فکر نمی کنم جواب دهد.
موفق باشید.
سلام ، ممنون از آموزش خیلی خوبتون. من میخواستم طبق اموزش شما این کدها رو ابتدا روی دو امولاتور (Memu) تست کنم. طبق توضیحات شما telnet رو فعال کردم و دستور telnet localhost 5037 رو تو cmd اجرا کردم و پنجره telnet localhost برام باز میشه ولی همینکه میخوام دستوری توش تایپ کنم این پنجره میپره (انگار بسته میشه) و برمیگردم تو پنجره ی cmd… نمیدونم مشکل از کجا میتونه باشه. ممنون میشم اگه موردی بنظرتون میرسه راهنماییم کنید. یک مورد دیگه اینکه به جای SERVER_IP باید آی پی امولاتوری که برنامه سرور روش اجرا میشه رو بذاریم، درسته؟
با عرض سلام و خسته نباشید.
بنده یک سوال دارم,کدی هست که آی پی دستگاه خود یا همون کلاینت رو نشون بده و با استفاده از همون آی پی یک پورت توی شبکه باز کرد؟مثلا آی پی یک دستگاه که تو شبکه لن(دستگاهی که هات اسپات کرده) 192.168.0.1 هست و در برنامه با سوکت پورت را در آی پی باز کرد نهایتش پورت باز شده برای ارسال اطلاعات میشه 192.168.0.1:41123 ; در کلاینت هم برنامه فقط به همین آی پی و پورت وصل بشه که البته اول باید فعال بودن آی پی(وای فای) را چک کنه. بدین صورت بدون نیاز به دردسر های Port Forwarding بین دو کلاینت تبادل اطلاعات بشه.
سلام و درود
سورس زیر به کارتون میادش چیزی که می خواهید رو دارد.
https://github.com/elixsr/FwdPortForwardingApp
موفق و پیروز باشید.
سلام و درود . واقعا سایت عالیه. من کد های سمت کلاینت رو سرور خودم که امتحان کردم به مشکلی عجیب برخورم مشکل این بود که وقتی وصل می شدم پیام ارسال می کنم به اون دیگه پیام ارسال نمی شد یا به عبارتی دیگر فقط یه بار پیام ارسال می شد. اما وقتی دوباره ارتباط و وصل می کردم می شد پیام ارسال کرد.
در مورد پیامی که سرور می زم تا وقتی کلاینت قطع نمی شد پیام نمی رسد
کمکم کنید لطفا با تشکر
سلام من میخوام ارتباط بین برنامه اندروید با یک دستگاه رطوبت سنج که یک ip ثابت روش ست شده از طریق tcp , udp برقرار کنم میشه لطفا راهنمایی کنید باید چکار کنم ممنون میشم