Socket 編程基礎知識:
主要分伺服器端編程和用戶端編程。
伺服器端編程步驟:
1: 建立伺服器端通訊端並綁定到一個連接埠上(0-1023是系統預留的,最好大約1024)
2: 通訊端設定監聽模式等待串連請求
3: 接受串連請求後進行通訊
4: 返回,等待贏一個串連請求
用戶端編程步驟:
1: 建立用戶端通訊端(指定伺服器端IP地址與連接埠號碼)
2: 串連(Android 建立Socket時會自動連接)
3: 與伺服器端進行通訊
4: 關閉通訊端
Android Socket 通訊原理注意:
1: 中間的管道串連是通過InputStream/OutputStream流實現的。
2: 一旦管道建立起來可進行通訊
3: 關閉管道的同時意味著關閉Socket
4: 當對同一個Socket建立重複管道時會異常
5: 通訊過程中順序很重要:伺服器端首先得到輸入資料流,然後將輸入資料流資訊輸出到其各個用戶端
用戶端先建立串連後先寫入輸出資料流,然後再獲得輸入資料流。不然活有EOFException的異常。
不要忘記添加Internet許可權,不要忘記添加Internet許可權,不要忘記添加Internet許可權
伺服器端代碼的編寫:
import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;import java.util.ArrayList;public class Server {static ServerSocket aServerSocket = null; // Server Socet.DataInputStream aDataInput = null; // Server input Stream that to// receive msg from client.DataOutputStream aDataOutput = null; // Server output Stream that tostatic ArrayList list = new ArrayList();public static void main(String[] args) {try {aServerSocket = new ServerSocket(50003); // listen 8888 port.System.out.println("already listen 50003 port.");} catch (Exception e) {e.printStackTrace();}int num = 0;while (num < 10) {Socket aSessionSoket = null;try {aSessionSoket = aServerSocket.accept();MyThread thread = new Server().new MyThread(aSessionSoket);thread.start();num = list.size();} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}}class MyThread extends Thread {Socket aSessionSoket = null;public MyThread(Socket socket) {aSessionSoket = socket;}public void run() {try {aDataInput = new DataInputStream(aSessionSoket.getInputStream());aDataOutput = new DataOutputStream(aSessionSoket.getOutputStream());list.add(aDataOutput);while (true) {String msg = aDataInput.readUTF(); // read msg.if (!msg.equals("connect...")) {System.out.println("ip: "+ aSessionSoket.getInetAddress());// ip.System.out.println("receive msg: " + msg);for (int i = 0; i < list.size(); i++) {DataOutputStream output = (DataOutputStream) list.get(i);output.writeUTF(msg + "----" + list.size());}if (msg.equals("end"))break;}aDataOutput.writeUTF("");}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {try {aDataInput.close();if (aDataOutput != null)aDataOutput.close();list.remove(aDataOutput);aSessionSoket.close();} catch (Exception e2) {
注意問題:為了實現對於多個用戶端的處理,使用了多線程的操作,每個線程維護一個Socket的串連與通訊,新串連的Socket的管道被加入到 ArrayList中。對於輸出資料流的操作是對於所有的串連的用戶端進行寫資料。對於關閉了Socket的用戶端管道從List中移除。
用戶端代碼的編寫:
import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.InetSocketAddress;import java.net.Socket;import java.net.SocketAddress;import java.net.UnknownHostException;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;public class SocketActivity extends Activity {EditText editText = null;Button sendButton = null;TextView display = null;Socket client = null;MyHandler myHandler;DataOutputStream dout;DataInputStream din;public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.clientsocket);editText = (EditText) findViewById(R.id.message);sendButton = (Button) findViewById(R.id.send);display = (TextView) findViewById(R.id.display);sendButton.setOnClickListener(listener);try {client = new Socket("192.168.0.120", 50003);dout = new DataOutputStream(client.getOutputStream());din = new DataInputStream(client.getInputStream());} catch (UnknownHostException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}myHandler = new MyHandler();MyThread m = new MyThread();m.start();}class MyHandler extends Handler {public MyHandler() {}// 子類必須重寫此方法,接受資料@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubLog.d("MyHandler", "handleMessage......");super.handleMessage(msg);// 此處可以更新UIif (client != null && client.isConnected()) {Log.i("handler..", "*-----*");try {dout.writeUTF("connect...");String message = din.readUTF();if (!message.equals(""))display.setText(display.getText().toString() + " "+ "伺服器發來的訊息--:" + message);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}class MyThread extends Thread {public void run() {while (true) {try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}Message msg = new Message();SocketActivity.this.myHandler.sendMessage(msg);}}}OnClickListener listener = new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubString sendText = editText.getText().toString();try {// din = new DataInputStream(client.getInputStream());dout.writeUTF(sendText);/** display.setText(display.getText().toString() + " " +* "伺服器發來的訊息:" + din.readUTF());*//** display.setText(display.getText().toString() + " " +* "伺服器發來的訊息--:" + din.readUTF());*/} catch (UnknownHostException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}};}