fangchongbory的专栏

Socket通常也称作“套接字”,用于描述IP地址和端口,是一个通信连的句柄。应用程序通常通过“套接字”向网络发送请求或者应答网络请求

一个客户端要发起一次通信,首先必须知道运行服务器端的主机IP地址和通信端口。然后由网络基础设施利用目标地址,将客户端发送的信息传递到正确的主机上,在Java中,地址可以由字符串来定义,字符串可以使数字型的地址(比如192.168.1.108),也可以是主机名,端口为6000

下面实现一个例子,手机为客户端,PC机(linux系统)为服务器,手机和服务器约定一个端口号6000.手机通过socket向服务器发送命令,服务器监听约定的端口号6000,接收来自客户端的socket套接字,执行命令,并将命令返回给手机客户端。手机客户端接收服务器返回的消息,并将消息显示出来。从而实现从手机端发送服务器发送命令,并显示服务器端执行命令后的结果。采用这种方法,可以使用手机控制服务器的运行,譬如重启,关机,查看文件等。

实例:

服务器端

package com.android.server;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;}//关闭socketprivate 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();}}}手机客户端:package com.control;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.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.content.SharedPreferences;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.text.TextUtils;import android.text.method.ScrollingMovementMethod;import android.util.Log;import android.view.KeyEvent;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;public class ControlActivity extends Activity {//服务器ip地址public static final String DEFULT_PRES = "192.168.1.108";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 EditText ipEdit;private TextView log;private Button send;private Button clean;private String ip;private String logMsg;private Socket socket;private BufferedWriter writer;private InetSocketAddress isa = null;Context mContext;public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);mContext = this;findviews();setonclick();init();}public void findviews() {command = (EditText) this.findViewById(R.id.command);log = (TextView) this.findViewById(R.id.log);send = (Button) this.findViewById(R.id.send);ipEdit = (EditText) this.findViewById(R.id.ipEdit);clean = (Button) this.findViewById(R.id.clean);}private void init() {log.setMovementMethod(ScrollingMovementMethod.getInstance());logMsg = log.getText().toString();//创建一个socket实例socket = new Socket();ip = onLoad();if (ip != null) {ipEdit.setText(ip);}}private void setonclick() {send.setOnClickListener(new View.OnClickListener() {public void onClick(View v) {ip = ipEdit.getText().toString();//当点击发送按钮时,开启一个tcpClient线程,向服务器发送消息tcpClient tcp = new tcpClient(command.getText().toString());tcp.start();}});clean.setOnClickListener(new Button.OnClickListener() {public void onClick(View v) {// TODO Auto-generated method stublogMsg = "";log.setText(logMsg);}});}//在向服务器发送消息之前,必须先链接到服务器。public void connecttoserver() throws UnknownHostException, IOException {socket = RequestSocket(ip, PORT);//判断是否链接成功if (socket.isConnected()) {Message msg = new Message();msg.what = CONNENTED;mHandler.sendMessage(msg);}}//链接服务器private Socket RequestSocket(String host, int port)throws UnknownHostException, IOException {Socket ConSocket = new Socket();//创建套接字地址,其中 IP 地址为通配符地址,端口号为指定值。//有效端口值介于 0 和 65535 之间。端口号 zero 允许系统在 bind 操作中挑选暂时的端口。 isa = new InetSocketAddress(host, port);//建立一个远程链接ConSocket.connect(isa);return ConSocket;}//向服务器发送信息private void SendMsg(Socket socket, String msg) throws IOException {writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));Log.i("msg", msg.replace("\n", " ") + "\n");writer.write(msg.replace("\n", " ") + "\n");writer.flush();}// 接收服务器信息private String ReceiveMsg(Socket socket) throws IOException {BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));String line;String txt = "";while ((line = reader.readLine()) != null) {txt += line + "\n";}reader.close();return txt;}class tcpClient extends Thread {String commandString;public tcpClient() {commandString = "ls";}public tcpClient(String command) {commandString = command;}public void run() {String recv;try {connecttoserver();//向服务器发送命令SendMsg(socket, commandString);//等待,,接收来自服务器返回的消息recv = ReceiveMsg(socket);if (recv != null) {logMsg += recv;// close BufferedWriter and socketwriter.close();socket.close();// 将服务器返回的消息显示出来Message msg = new Message();msg.what = UPDATALOG;mHandler.sendMessage(msg);}} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}private String onLoad() {SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);String mPreferences = settings.getString("preferences", DEFULT_PRES);return mPreferences;}private void onSave(String save) {if (TextUtils.isEmpty(save)) {setPreferences(DEFULT_PRES);} else {setPreferences(save);}}private void setPreferences(String mPreferences) {SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);SharedPreferences.Editor editor = settings.edit();editor.putString("preferences", mPreferences);editor.commit();}public boolean onKeyDown(int keyCode, KeyEvent event) {if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {AlertDialog.Builder builder = new AlertDialog.Builder(this);builder.setTitle("PC Control");builder.setMessage("exit ?");builder.setPositiveButton("Yes",new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {onSave(ipEdit.getText().toString());finish();}});builder.setNegativeButton("Cancel",new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {}});builder.show();}return super.onKeyDown(keyCode, event);}public boolean onCreateOptionsMenu(Menu menu) {menu.add(0, 1, 1, "关机");menu.add(0, 2, 2, "重启");menu.add(0, 3, 3, "退出");return super.onCreateOptionsMenu(menu);}public boolean onOptionsItemSelected(MenuItem item) {switch (item.getItemId()) {case 1:tcpClient tcp = new tcpClient("sudo poweroff");tcp.start();return true;case 2:tcp = new tcpClient("sudo reboot");tcp.start();return true;case 3:finish();break;}return super.onOptionsItemSelected(item);}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;}}};}并记得在 AndroidManifest.xml注册权限 <uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

好了,大家可以在自己电脑上试试,有什么问题,大家交流一下,彼此学习!

原文来自

最困难之时,就是我们离成功不远之日。

fangchongbory的专栏

相关文章:

你感兴趣的文章:

标签云: