在Android上使用Socket
原文地址:http://www.cnblogs.com/kross/p/3621952.html
?
考慮到以后可能要用到這方面的知識(shí),就來寫個(gè)Demo嘗試下,其實(shí)以前學(xué)過,但不記得了……(用不到的東西各種不記得啊)
直接進(jìn)入正題吧,在Android上使用Socket實(shí)際上跟在Java中使用差不多,只要注意下在Manifest中加網(wǎng)絡(luò)權(quán)限就好了(我原來經(jīng)常犯這個(gè)錯(cuò)誤),另外網(wǎng)絡(luò)請(qǐng)求不能再主線程里,基本就OK了。
そして,先寫一個(gè)服務(wù)器的小程序吧。就直接使用Java寫就好了,灰常的簡單,隨便寫寫。
/*** 測試服務(wù)器* */ public class TestServer {public static void main(String[] args) throws IOException {ServerSocket ss = new ServerSocket(5417);Socket client = null;while (true) {System.out.println("waiting for...");client = ss.accept();BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));System.out.println(br.readLine());}} }然后我的構(gòu)想是,手機(jī)上有一個(gè)輸入框,一個(gè)按鈕,用戶可以按按鈕,把輸入框里的內(nèi)容發(fā)送到服務(wù)器上。一開始我寫了一個(gè)很混亂的demo,為了更加方便使用,就把Socket的封裝了一下,就叫SocketManager吧,代碼如下:
/*** SocketManager,簡單的封裝了一下* @author Kross(krossford@foxmail.com)* @date 2014-3-24 21:39:48* */ public class SocketManager {private Socket client = null;//服務(wù)器的IP地址private String ip = "113.251.172.30";//監(jiān)聽的端口號(hào)private int port = 5417;/*** 獲取一個(gè)實(shí)例* */public static SocketManager newInstance() throws UnknownHostException, IOException {return new SocketManager();}private SocketManager() throws UnknownHostException, IOException {client = new Socket(ip, port);}/*** 發(fā)送一條消息* @param msg 消息內(nèi)容* */public void sendMessage(String msg) throws IOException {PrintWriter printWriter = new PrintWriter(client.getOutputStream());printWriter.print(msg);printWriter.flush();printWriter.close(); //一定要關(guān)閉輸出流,要不然消息無法送達(dá)到服務(wù)器 } }幾個(gè)要點(diǎn):
1.IP地址就寫Java程序鎖運(yùn)行的機(jī)器的公網(wǎng)地址,cmd->ipconfig就可以查到。
2.端口號(hào)請(qǐng)和服務(wù)器那個(gè)保持一致,都不在一個(gè)管道里怎么通信哇。
3.我使用了靜態(tài)工廠方法,每次都要重新new一個(gè)SocketManager,因?yàn)槲野l(fā)現(xiàn)Socket這個(gè)類只能用一次,close之后再發(fā)送便沒用了。
4.服務(wù)器要收到信息,必須要客戶端的東西close了,輸出流close也好,socket.close也好,總之要close,服務(wù)器才能確切的收到。
然后,我寫了一個(gè)線程來執(zhí)行這個(gè)Socket,因?yàn)椴荒茉谥骶€程跑嘛,我想了很久,可不可以讓這個(gè)線程一直執(zhí)行著,然后只要調(diào)用下這個(gè)線程的sendMessage方法,就可以發(fā)送了,這樣就只需要new一個(gè)線程就行了,但是我想了好久,都想不通,貌似不能那樣,線程要么沒有,有的話就會(huì)一股腦的執(zhí)行它的run()方法,想要長時(shí)間持有它?在run里面加個(gè)while(true)?那怎么做到調(diào)用它的共有方法呢?總之,我沒有想到用只需要new一個(gè)線程就可以發(fā)N個(gè)請(qǐng)求的辦法,貌似需要使用到Service來實(shí)現(xiàn)了。
/*** 發(fā)起請(qǐng)求的線程* @author Kross(krossford@foxmail.com)* @date 2014-3-24 21:40:21* */ public class SocketThread implements Runnable {private String message;public SocketThread(String msg) {message = msg;}@Overridepublic void run() {try {SocketManager.newInstance().sendMessage(message);} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}} }這里倒沒什么好說的。接下來我們就直接在MainActivity里面準(zhǔn)備好控件,監(jiān)聽器,然后就OK了,大致的看下代碼吧。
public class MainActivity extends Activity {private EditText etInput = null;private Button bSend = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Log.i("MainActivity", Thread.currentThread().getName());etInput = (EditText)findViewById(R.id.et_input);bSend = (Button)findViewById(R.id.b_send);bSend.setOnClickListener(new SendButtonListener());}class SendButtonListener implements OnClickListener {@Overridepublic void onClick(View v) {String msg = etInput.getEditableText().toString().trim();new Thread(new SocketThread(msg)).start();etInput.setText("");}} }OK,代碼就是這樣了,來看下最終的運(yùn)行效果吧。
先啟動(dòng)Java的服務(wù)器程序,啟動(dòng)后結(jié)果是這樣的:
然后我們運(yùn)行手機(jī)上的程序,發(fā)送一條消息:
再來看服務(wù)器端的程序:
看上去一切正常,再來一發(fā)!
再看看服務(wù)器的程序:
OK,看來是沒有問題了。
?
服務(wù)器如何向Socket返回信息暫時(shí)還沒有去實(shí)驗(yàn),留著明天來搞吧……
?
原文地址:http://www.cnblogs.com/kross/p/3621952.html
新浪微博:http://weibo.com/KrossFord
轉(zhuǎn)載于:https://www.cnblogs.com/kross/p/3621952.html
總結(jié)
以上是生活随笔為你收集整理的在Android上使用Socket的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JSP+JavaBean+Servlet
- 下一篇: curl访问nagios中Host St