1.首先直接看服务器端代码:
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; import java.io.LineNumberReader; public class Server extends Thread { private ServerSocket server = null; private static final int PORT = 6000; private BufferedWriter writer; private BufferedReader reader; private Server() throws IOException { // 创建Socket服务器 CreateSocket(); } public void run() { Socket client; String txt; try { // 线程无限循环,实时监听socket端口 while (true){ client = ResponseSocket(); // 响应客户端链接请求。。 while (true) { txt = ReceiveMsg(client); // 链接获得客户端发来的命令 System.out.println(txt); if (txt != null) { // 执行命令 txt = exceCommand(txt); } // 向客户端返回消息 SendMsg(client, txt); // 中断,关闭此次连接 break; } CloseSocket(client); } } catch (IOException e) { System.out.println(e); } } //创建一个ServerSocket实例,绑定到一个特定的端口。一个服务器端口最多可以支持50个链接,超出了则拒绝链接。 //所以,最多只能有50个客户端同时使用这个指定的端口向服务器发送消息 private void CreateSocket() throws IOException { server = new ServerSocket(PORT); System.out.println("Server starting.."); } /* ServerSocket:这个类是实现了一个服务器端的Socket,利用这个类可以监听来自网络的请求。 1、创建ServerSocket的方法: ServerSocket(Int localPort) ServerSocket(int localport,int queueLimit) ServerSocket(int localport,int queueLimit,InetAddress localAddr) 创建一个ServerSocket必须指定一个端口,以便客户端能够向该端口号发送连接请求。端口的有效范围是0-65535 2、ServerSocket操作 Socket accept() void close accept()方法为下一个传入的连接请求创建Socket实例,并将已成功连接的Socket实例返回给服务器套接字,如果没有连接请求, accept()方法将阻塞等待; close方法用于关闭套接字 */ private Socket ResponseSocket() throws IOException { Socket client = server.accept(); System.out.println("client connected.."); return client; } //关闭socket private void CloseSocket(Socket socket) throws IOException { reader.close(); writer.close(); socket.close(); System.out.println("client closed.."); } //向客户端发送消息 private void SendMsg(Socket socket, String Msg) throws IOException { writer = new BufferedWriter(new OutputStreamWriter( socket.getOutputStream())); writer.write(Msg + "\n"); writer.flush(); } //接收来自客户端的消息。服务器通过server.accept();接收来自客户端的套接字,采用I/O方式 //将套接字的消息取出来 private String ReceiveMsg(Socket socket) throws IOException { reader = new BufferedReader(new InputStreamReader( socket.getInputStream())); System.out.println("server get input from client socket.."); String line = null; while ((line = reader.readLine()) != null) { System.out.println(line); return line; } return line; } //执行客户端发送来的命令。服务器将在本机执行客户端发送过来的消息(命令)。 //并返回执行命令后,服务器返回的结果。譬如,在linux下执行“ls”命令,返回的是当前目录 //下面的所有文件的名称 private String exceCommand(String command) { String msg = ""; try { //Runtime.getRuntime()返回当前应用程序的Runtime对象,该对象的exec() //方法指示Java虚拟机创建一个子进程执行指定的可执行程序(命令),并返回与该子进程对应的Process对象实例。 //通过Process可以控制该子进程的执行或获取该子进程的信息 Process process = Runtime.getRuntime().exec(command); InputStreamReader ir = new InputStreamReader( process.getInputStream()); LineNumberReader input = new LineNumberReader(ir); String line; while ((line = input.readLine()) != null) { System.out.println(line); msg += line + "\n"; } } catch (java.io.IOException e) { System.err.println("IOException " + e.getMessage()); } return msg; } public static void main(final String args[]) throws IOException { Server commandServer = new Server(); if (commandServer != null) { // commandServer.stop(); commandServer.start(); } } }
2、Android客户端activity_main.xml代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <TextView android:id="@+id/textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" /> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/edittext" android:hint="请输入内容" /> <Button android:id="@+id/send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="发送" ></Button> </LinearLayout>
3、Android客户端Activity.java代码:
package com.example.socket2; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.text.method.ScrollingMovementMethod; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends Activity { //服务器ip地址 public static final String DEFULT_PRES = "192.168.56.1"; public static final String PREFS_NAME = "PreferencesFile"; public static final int CONNENTED = 0; public static final int UPDATALOG = 1; private static final int PORT = 6000; private EditText command; private TextView log; private Button send; private String ip; private String logMsg; private Socket socket; private BufferedWriter writer; private InetSocketAddress isa = null; Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case CONNENTED: logMsg += "Server Connented\n"; log.setText(logMsg); break; case UPDATALOG: log.setText(logMsg); log.setScrollContainer(true); break; } } }; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findviews(); init(); setonclick(); } public void findviews() { command = (EditText) this.findViewById(R.id.edittext); log = (TextView) this.findViewById(R.id.textview); send = (Button) this.findViewById(R.id.send); } private void init() { log.setMovementMethod(ScrollingMovementMethod.getInstance()); logMsg = log.getText().toString(); //创建一个socket实例 socket = new Socket(); ip ="192.168.56.1" ; } private void setonclick() { send.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { ip = "192.168.56.1"; //当点击发送按钮时,开启一个tcpClient线程,向服务器发送消息 tcpClient tcp = new tcpClient(command.getText().toString()); tcp.start(); } }); } class tcpClient extends Thread { String commandString; public tcpClient() { commandString = "ls"; } public tcpClient(String command) { commandString = command; } public void run() { String recv; try { Socket ConSocket = new Socket(); //创建套接字地址,其中 IP 地址为通配符地址,端口号为指定值。 //有效端口值介于 0 和 65535 之间。端口号 zero 允许系统在 bind 操作中挑选暂时的端口。 isa = new InetSocketAddress(ip, PORT); //建立一个远程链接 ConSocket.connect(isa); //socket.connect(isa); socket=ConSocket; if (socket.isConnected()) { Message msg = new Message(); msg.what = CONNENTED; mHandler.sendMessage(msg); } //向服务器发送命令 writer = new BufferedWriter(new OutputStreamWriter( socket.getOutputStream())); Log.i("msg", commandString.replace("\n", "")+"\n"); writer.write(commandString.replace("\n", "")+"\n"); writer.flush(); //等待,接收来自服务器返回的消息 BufferedReader reader = new BufferedReader(new InputStreamReader( socket.getInputStream())); String line; String txt = ""; while ((line = reader.readLine()) != null) { txt += line + "\n"; } reader.close(); recv = txt; if (recv != null) { logMsg += recv; // close BufferedWriter and socket writer.close(); socket.close(); // 将服务器返回的消息显示出来 Message msg = new Message(); msg.what = UPDATALOG; mHandler.sendMessage(msg); } } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } }
4、在清单文件中增加两条授权:(重要)
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />