Android客戶端與服務器端的Socket通信:java
socket通信依賴IP地址和端口號,每種服務都打開一個Socket,並綁定到一個端口上,不一樣的端口對應於不一樣的服務。android
服務器端代碼:服務器
實例化主類,定義端口號的主方法:app
package com.example.socketdemoclient; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Main { private static final int PORT = 9999; private List<Socket> mList = new ArrayList<Socket>(); private ServerSocket server = null; private ExecutorService mExecutorService = null; //thread pool public static void main(String[] args) { new Main(); } public Main() { try { //實例化一個Socket服務 server = new ServerSocket(PORT); //啓動一個線程池 mExecutorService = Executors.newCachedThreadPool(); //create a thread pool System.out.println("服務器已啓動..."); Socket client = null; while(true) { client = server.accept(); //把客戶端放入客戶端集合中 mList.add(client); mExecutorService.execute(new Service(client)); //start a new thread to handle the connection } }catch (Exception e) { e.printStackTrace(); } } class Service implements Runnable { private Socket socket; private BufferedReader in = null; private String msg = ""; public Service(Socket socket) { this.socket = socket; try { in = new BufferedReader(new InputStreamReader(socket.getInputStream())); //客戶端只要一連到服務器,便向客戶端發送下面的信息。 msg = "服務器地址:" +this.socket.getInetAddress() + "come toal:" +mList.size()+"(服務器發送)"; this.sendmsg(); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { try { while(true) { if((msg = in.readLine())!= null) { //當客戶端發送的信息爲:exit時,關閉鏈接 if(msg.equals("exit")) { System.out.println("ssssssss"); mList.remove(socket); in.close(); msg = "user:" + socket.getInetAddress() + "exit total:" + mList.size(); socket.close(); this.sendmsg(); break; //接收客戶端發過來的信息msg,而後發送給客戶端。 } else { msg = socket.getInetAddress() + ":" + msg+"(服務器發送)"; this.sendmsg(); } } } } catch (Exception e) { e.printStackTrace(); } } /** * 循環遍歷客戶端集合,給每一個客戶端都發送信息。 */ public void sendmsg() { System.out.println(msg); int num =mList.size(); for (int index = 0; index < num; index ++) { Socket mSocket = mList.get(index); PrintWriter pout = null; try { pout = new PrintWriter(new BufferedWriter( new OutputStreamWriter(mSocket.getOutputStream())),true); pout.println(msg); }catch (IOException e) { e.printStackTrace(); } } } } }
socket服務Server類:socket
package com.test.socket.message; import java.io.*; import java.net.*; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; import javax.swing.JOptionPane; public class Server { ServerSocket ss = null; private String getnameString=null; boolean started = false; List<Client> clients = new ArrayList<Client>(); List<Info> infos = new ArrayList<Info>(); public static void main(String[] args) { //彈出框,出入端口號 String inputport = JOptionPane.showInputDialog("請輸入該服務器使用的端口:"); int port = Integer.parseInt(inputport); new Server().start(port); } public void start(int port) { try { ss = new ServerSocket(port); System.out.println("服務器啟動"); started = true; } catch (BindException e) { System.out.println(" 端口已經被佔用"); System.exit(0); } catch (IOException e) { e.printStackTrace(); } try { while (started) { Socket s = ss.accept(); Client c = new Client (s); System.out.println("a client is connected"); new Thread(c).start(); clients.add(c); } } catch (IOException e) { e.printStackTrace(); } finally { try { ss.close(); } catch (IOException e) { e.printStackTrace(); } } } public List<Client> getClient(){ return clients; } class Client implements Runnable { private String chatKey="SLEEKNETGEOCK4stsjeS"; private Socket s = null; private DataInputStream dis = null; private DataOutputStream dos = null; private boolean bConnected = false; private String sendmsg=null; Client (Socket s) { this.s = s; try { dis = new DataInputStream (s.getInputStream()); dos = new DataOutputStream (s.getOutputStream()); bConnected = true; } catch(IOException e) { e.printStackTrace(); } } public void send (String str) { try { //System.out.println(s); dos.writeUTF(str+""); dos.flush(); } catch(IOException e) { clients.remove(this); System.out.println("對方已經退出了"); } } public void run() { try { while (bConnected) { String str = dis.readUTF(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String date = " ["+df.format(new Date())+"]"; if(str.startsWith(chatKey+"online:")){ Info info = new Info(); getnameString = str.substring(27); info.setName(getnameString); infos.add(info); for (int i=0; i<clients.size(); i++) { Client c = clients.get(i); c.send(getnameString+" on line."+date); } System.out.println(getnameString+" on line."+date); }else if(str.startsWith(chatKey+"offline:")){ getnameString = str.substring(28); clients.remove(this); for (int i=0; i<clients.size(); i++) { Client c = clients.get(i); c.send(getnameString+" off line."+date); } System.out.println(getnameString+" off line."+date); } else{ int charend = str.indexOf("end;"); String chatString = str.substring(charend+4); String chatName = str.substring(25, charend); sendmsg=chatName+date+"\n"+chatString; for (int i=0; i<clients.size(); i++) { Client c = clients.get(i); c.send(sendmsg); } System.out.println(sendmsg); } } } catch (SocketException e) { System.out.println("client is closed!"); clients.remove(this); } catch (EOFException e) { System.out.println("client is closed!"); clients.remove(this); } catch (IOException e) { e.printStackTrace(); } finally { try { if (dis != null) dis.close(); if (dos != null) dos.close(); if (s != null) s.close(); } catch (IOException e) { e.printStackTrace(); } } } } class Info{ private String info_name = null; public Info(){ } public void setName(String name){ info_name = name; } public String getName(){ return info_name; } } }
服務器端代碼:ide
Android客戶端:ui
package com.example.socketdemoclient; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends Activity implements Runnable { private TextView tv_msg = null; private EditText ed_msg = null; private Button btn_send = null; // private Button btn_login = null; private static final String HOST = "10.0.2.2"; private static final int PORT = 9999; private Socket socket = null; private BufferedReader in = null; private PrintWriter out = null; private String content = ""; // 接收線程發送過來信息,並用TextView顯示 public Handler mHandler = new Handler() { public void handleMessage(Message msg) { super.handleMessage(msg); tv_msg.setText(content); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_msg = (TextView) findViewById(R.id.TextView); ed_msg = (EditText) findViewById(R.id.EditText01); btn_send = (Button) findViewById(R.id.Button02); try { socket = new Socket(HOST, PORT); in = new BufferedReader(new InputStreamReader( socket.getInputStream())); out = new PrintWriter(new BufferedWriter(new OutputStreamWriter( socket.getOutputStream())), true); } catch (IOException ex) { ex.printStackTrace(); ShowDialog("login exception" + ex.getMessage()); } btn_send.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub String msg = ed_msg.getText().toString(); if (socket.isConnected()) { if (!socket.isOutputShutdown()) { out.println(msg); } } } }); // 啓動線程,接收服務器發送過來的數據 new Thread(MainActivity.this).start(); } /** * 若是鏈接出現異常,彈出AlertDialog! */ public void ShowDialog(String msg) { new AlertDialog.Builder(this).setTitle("notification").setMessage(msg) .setPositiveButton("ok", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }).show(); } /** * 讀取服務器發來的信息,並經過Handler發給UI線程 */ public void run() { try { while (true) { if (!socket.isClosed()) { if (socket.isConnected()) { if (!socket.isInputShutdown()) { if ((content = in.readLine()) != null) { content += "\n"; mHandler.sendMessage(mHandler.obtainMessage()); } else { } } } } } } catch (Exception e) { e.printStackTrace(); } } }
權限:this
<uses-permission android:name="android.permission.INTERNET" />.net