實(shí)現(xiàn)了基本的socket通信(即兩臺(tái)設(shè)備,一臺(tái)用作服務(wù)器,一臺(tái)用作客戶端),服務(wù)器進(jìn)行監(jiān)聽,客戶端發(fā)送加密數(shù)據(jù)到服務(wù)器,服務(wù)器進(jìn)行解密得到明文。
成都創(chuàng)新互聯(lián)主要從事成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、網(wǎng)頁設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)江源,十多年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):028-86922220
注意:本項(xiàng)目中使用了ButterKnife及EventBus作為輔助工具,通信建立時(shí)默認(rèn)網(wǎng)絡(luò)正常(未做局域網(wǎng)網(wǎng)絡(luò)環(huán)境檢測(cè)),加密方式為AES加密
1.效果圖:
(1)客戶端
(2)服務(wù)器端
2.界面布局部分
(1)服務(wù)器端布局 function_socket_server.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <RelativeLayout > <TextView android:text="網(wǎng)絡(luò)加密-服務(wù)器端" /> </RelativeLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_startListener" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="啟動(dòng)監(jiān)聽" /> <Button android:id="@+id/btn_stopListener" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="停止監(jiān)聽" /> <Button android:id="@+id/btn_getUser" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="刷新用戶" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="本機(jī)地址:" /> <TextView android:id="@+id/tv_localAddress" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" /> </LinearLayout> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="接收到的明文:" android:textColor="@color/black" /> <TextView android:id="@+id/tv_receivedContent" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="解密后的明文:" android:textColor="@color/black" /> <TextView android:id="@+id/tv_decryptContent" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp" /> </LinearLayout> </ScrollView> </LinearLayout>
(2)客戶端布局 function_socket_client.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <RelativeLayout > <TextView android:text="網(wǎng)絡(luò)加密-客戶端" /> </RelativeLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="服務(wù)器地址:" /> <EditText android:id="@+id/edtTxt_serverAddress" android:layout_width="match_parent" android:text="192.168.43.1" android:layout_height="wrap_content" android:singleLine="true" /> </LinearLayout> <ScrollView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="文本內(nèi)容:" android:textColor="@color/black" /> <EditText android:id="@+id/edtTxt_Content" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/main_background" android:padding="10dp" android:text="123木頭人" /> </LinearLayout> </ScrollView> <Button android:id="@+id/btn_encryptAndSend" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:text="加密并發(fā)送" /> </LinearLayout>
(3)用到的style
<!--通用Title的右側(cè)按鈕--> <style name="ToolBar_iv_Right"> <item name="android:layout_width">@dimen/toolbar_icon_dimen</item> <item name="android:layout_height">@dimen/toolbar_icon_dimen</item> <item name="android:layout_alignParentRight">true</item> <item name="android:layout_gravity">end</item> <item name="android:clickable">true</item> <item name="android:background">?android:actionBarItemBackground</item> <item name="android:padding">15dp</item> </style> <!--通用Title的TextView--> <style name="ToolBar_tv_Title"> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">wrap_content</item> <item name="android:layout_centerVertical">true</item> <item name="android:layout_marginLeft">@dimen/toolbar_title_haveBack_marginStart</item> <item name="android:layout_marginRight">@dimen/toolbar_title_haveBack_marginEnd</item> <item name="android:gravity">center</item> <item name="android:singleLine">true</item> <item name="android:textColor">@color/white</item> <item name="android:textSize">20sp</item> </style>
3.功能代碼
(1)基類 BaseEventActivity.Java
import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import org.greenrobot.eventbus.EventBus; import butterknife.ButterKnife; public abstract class BaseEventActivity extends AppCompatActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getIntentData(); setContentView(getLayoutResId()); ButterKnife.bind(this); EventBus.getDefault().register(this); init(); } protected void getIntentData() { } @Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); } protected abstract void init(); protected abstract int getLayoutResId(); }
(2)服務(wù)器主界面 Function_Socket.java
import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.view.View; import android.widget.TextView; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.io.BufferedReader; import java.io.FileReader; import java.util.ArrayList; import butterknife.BindView; import butterknife.OnClick; /** * 服務(wù)器界面 */ public class Function_Socket_Server extends BaseEventActivity { @BindView(R.id.tv_localAddress) TextView tv_localAddress; @BindView(R.id.tv_receivedContent) TextView tv_receivedContent; @BindView(R.id.tv_decryptContent) TextView tv_decryptContent; private LocalService localService;//用于啟動(dòng)監(jiān)聽的服務(wù) private ServiceConnection sc;//服務(wù)連接 @Override protected void init() { tv_localAddress.setText(ToolUtil.getHostIP()); sc = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { LocalService.LocalBinder localBinder = (LocalService.LocalBinder) service; localService = localBinder.getService(); localService.startWaitDataThread(); ToastUtil.showToast(Function_Socket_Server.this, "監(jiān)聽已啟動(dòng)"); } @Override public void onServiceDisconnected(ComponentName name) { } }; connection(); } @Subscribe(threadMode = ThreadMode.MAIN) public void getData(String data) { tv_receivedContent.setText(data); tv_decryptContent.setText(AESUtil.decrypt(ConstantUtil.password, data)); } /** * 綁定service */ private void connection() { Intent intent = new Intent(this, LocalService.class); bindService(intent, sc, BIND_AUTO_CREATE); } @Override protected int getLayoutResId() { return R.layout.function_socket_server; } /** * 獲取連接到本機(jī)熱點(diǎn)上的手機(jī)ip */ private ArrayList<String> getConnectedIP() { ArrayList<String> connectedIP = new ArrayList<>(); try { //通過讀取配置文件實(shí)現(xiàn) BufferedReader br = new BufferedReader(new FileReader( "/proc/net/arp")); String line; while ((line = br.readLine()) != null) { String[] splitted = line.split(" +"); if (splitted.length >= 4) { String ip = splitted[0]; connectedIP.add(ip); } } } catch (Exception e) { e.printStackTrace(); } return connectedIP; } @OnClick({R.id.btn_startListener, R.id.btn_stopListener, R.id.btn_getUser}) public void onClick(View v) { switch (v.getId()) { case R.id.btn_startListener://啟動(dòng)監(jiān)聽 connection(); break; case R.id.btn_stopListener://停止監(jiān)聽 if (sc != null) unbindService(sc); break; case R.id.btn_getUser://刷新連接到此設(shè)備的IP并清空之前接收到的數(shù)據(jù) ArrayList<String> connectedIP = getConnectedIP(); StringBuilder resultList = new StringBuilder(); for (String ip : connectedIP) { resultList.append(ip); resultList.append("\n"); } ToastUtil.showToast(this, "連接到手機(jī)上的Ip是:" + resultList.toString()); tv_decryptContent.setText(""); tv_receivedContent.setText(""); break; } } public void onDestroy() { super.onDestroy(); if (sc != null) unbindService(sc); } }
(3)客戶端主界面 Function_Socket_Client.java
import android.app.ProgressDialog; import android.util.Log; import android.view.View; import android.widget.EditText; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import butterknife.BindView; import butterknife.OnClick; /** * 客戶端界面 */ public class Function_Socket_Client extends BaseEventActivity { @BindView(R.id.edtTxt_Content) EditText edtTxt_Content; @BindView(R.id.edtTxt_serverAddress) EditText edtTxt_serverAddress; private ProgressDialog mProgressDialog;//加載的小菊花 /** * 初始化 */ @Override protected void init() { } @Override protected int getLayoutResId() { return R.layout.function_socket_client; } @OnClick(R.id.btn_encryptAndSend) public void onClick(View v) { switch (v.getId()) { case R.id.btn_encryptAndSend: String s = edtTxt_Content.getText().toString().trim(); String ip = edtTxt_serverAddress.getText().toString().trim(); if (ToolUtil.IsIpv4(ip)) { new SendDataThread(ip, AESUtil.encrypt(ConstantUtil.password, s), ConstantUtil.port).start();//消息發(fā)送方啟動(dòng)線程發(fā)送消息 showProgressDialog("嘗試發(fā)送數(shù)據(jù)到\n\t\t" + ip, true); } else { ToastUtil.showToast(this, "IP不合法!"); } break; } } /** * 連接結(jié)果 * * @param resultCode 0:連接超時(shí);1:發(fā)送成功 2:失敗 */ @Subscribe(threadMode = ThreadMode.MAIN) public void sendResult(Integer resultCode) { Log.i("succ", "=" + resultCode); dismissProgressDialog(); switch (resultCode) { case ConstantUtil.CODE_SUCCESS: ToastUtil.showToast(this, "發(fā)送成功"); break; case ConstantUtil.CODE_TIMEOUT: ToastUtil.showToast(this, "連接超時(shí)"); break; case ConstantUtil.CODE_UNKNOWN_HOST: ToastUtil.showToast(this, "錯(cuò)誤-未知的host"); break; } } /** * 數(shù)據(jù)加載小菊花 * * @param msg 內(nèi)容 * @param isCancel 是否允許關(guān)閉 true - 允許 false - 不允許 */ public void showProgressDialog(final String msg, final boolean isCancel) { runOnUiThread(new Runnable() { @Override public void run() { try { if (mProgressDialog == null) { mProgressDialog = new ProgressDialog(Function_Socket_Client.this); } if (mProgressDialog.isShowing()) { return; } mProgressDialog.setMessage(msg); mProgressDialog.setCancelable(isCancel); mProgressDialog.setCanceledOnTouchOutside(false); mProgressDialog.setOnCancelListener(null); mProgressDialog.show(); } catch (Exception e) { e.printStackTrace(); } } }); } /** * 隱藏?cái)?shù)據(jù)加載的進(jìn)度小菊花 **/ public void dismissProgressDialog() { try { if (mProgressDialog != null && mProgressDialog.isShowing()) { runOnUiThread( new Runnable() { @Override public void run() { mProgressDialog.dismiss(); } } ); } } catch (Exception e) { e.printStackTrace(); } } }
(4)LocalService.java
import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; /** * 此服務(wù)用于啟動(dòng)監(jiān)聽線程 */ public class LocalService extends Service { private IBinder iBinder = new LocalService.LocalBinder(); @Override public IBinder onBind(Intent intent) { return iBinder; } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; } public void startWaitDataThread() { new ListenThread(ConstantUtil.port).start(); } //定義內(nèi)容類繼承Binder public class LocalBinder extends Binder { //返回本地服務(wù) public LocalService getService() { return LocalService.this; } } }
(5)ListenThread.java
import org.greenrobot.eventbus.EventBus; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * 監(jiān)聽線程 */ public class ListenThread extends Thread { private ServerSocket serverSocket; public ListenThread(int port) { try { serverSocket = new ServerSocket(port); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { while (true) { try { if (serverSocket != null) { Socket socket = serverSocket.accept(); InputStream inputStream = socket.getInputStream(); if (inputStream != null) { BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); String str; str = in.readLine(); EventBus.getDefault().post(str); socket.close(); } } } catch (IOException e) { e.printStackTrace(); } } } }
(6)SendDataThread.java
import android.util.Log; import org.greenrobot.eventbus.EventBus; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketTimeoutException; import java.net.UnknownHostException; /** * 數(shù)據(jù)發(fā)送線程 */ public class SendDataThread extends Thread { private Socket socket; private String ip;//接收方的IP private int port;//接收方的端口號(hào) private String data;//準(zhǔn)備發(fā)送的數(shù)據(jù) public SendDataThread(String ip, String data, int port) { this.ip = ip; this.data = data; this.port = port; } @Override public void run() { try { socket = new Socket(); socket.connect(new InetSocketAddress(ip,port),ConstantUtil.TIME_MILLIS);//設(shè)置超時(shí)時(shí)間 } catch (UnknownHostException e) { EventBus.getDefault().post(ConstantUtil.CODE_UNKNOWN_HOST); Log.d("error", "SendDataThread.init() has UnknownHostException" + e.getMessage()); } catch (SocketTimeoutException e) { EventBus.getDefault().post(ConstantUtil.CODE_TIMEOUT); Log.d("error", "SendDataThread.init() has TimeoutException:" + e.getMessage()); }catch (IOException e){ Log.d("error", "SendDataThread.init() has IOException:" + e.getMessage()); } if (socket != null&&socket.isConnected()) { try { OutputStream ops = socket.getOutputStream(); OutputStreamWriter opsw = new OutputStreamWriter(ops); BufferedWriter writer = new BufferedWriter(opsw); writer.write(data + "\r\n\r\n");//由于socket使用緩沖區(qū)進(jìn)行讀寫數(shù)據(jù),因此使用\r\n\r\n用于表明數(shù)據(jù)已寫完.不加這個(gè)會(huì)導(dǎo)致數(shù)據(jù)無法發(fā)送 EventBus.getDefault().post(ConstantUtil.CODE_SUCCESS); writer.flush(); } catch (IOException e) { e.printStackTrace(); } } } }
(7)AESUtil.java
import android.util.Log; import java.io.UnsupportedEncodingException; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; /** * AES加密工具類 */ public class AESUtil { // private static final String CipherMode = "AES/ECB/PKCS5Padding";使用ECB加密,不需要設(shè)置IV,但是不安全 private static final String CipherMode = "AES/CFB/NoPadding";//使用CFB加密,需要設(shè)置IV /** * 生成加密后的密鑰 * * @param password 密鑰種子 * @return isSucceed */ private static SecretKeySpec createKey(String password) { byte[] data = null; if (password == null) { password = ""; } StringBuilder sb = new StringBuilder(32); sb.append(password); while (sb.length() < 32) { sb.append("0"); } if (sb.length() > 32) { sb.setLength(32); } try { data = sb.toString().getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return new SecretKeySpec(data, "AES"); } // /** 加密字節(jié)數(shù)據(jù) **/ private static byte[] encrypt(byte[] content, String password) { try { SecretKeySpec key = createKey(password); System.out.println(key); Cipher cipher = Cipher.getInstance(CipherMode); cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec( new byte[cipher.getBlockSize()])); return cipher.doFinal(content); } catch (Exception e) { e.printStackTrace(); } return null; } // /** 加密(結(jié)果為16進(jìn)制字符串) **/ public static String encrypt(String password, String content) { Log.d("加密前", "seed=" + password + "\ncontent=" + content); byte[] data = null; try { data = content.getBytes("UTF-8"); } catch (Exception e) { e.printStackTrace(); } data = encrypt(data, password); String result = byte2hex(data); Log.d("加密后", "result=" + result); return result; } // /** 解密字節(jié)數(shù)組 **/ private static byte[] decrypt(byte[] content, String password) { try { SecretKeySpec key = createKey(password); Cipher cipher = Cipher.getInstance(CipherMode); cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec( new byte[cipher.getBlockSize()])); return cipher.doFinal(content); } catch (Exception e) { e.printStackTrace(); } return null; } // /** 解密16進(jìn)制的字符串為字符串 **/ public static String decrypt(String password, String content) { Log.d("解密前", "seed=" + password + "\ncontent=" + content); byte[] data = null; try { data = hex2byte(content); } catch (Exception e) { e.printStackTrace(); } data = decrypt(data, password); if (data == null) return null; String result = null; try { result = new String(data, "UTF-8"); Log.d("解密后", "result=" + result); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return result; } // /** 字節(jié)數(shù)組轉(zhuǎn)成16進(jìn)制字符串 **/ private static String byte2hex(byte[] b) { // 一個(gè)字節(jié)的數(shù), StringBuilder sb = new StringBuilder(b.length * 2); String tmp ; for (byte aB : b) { // 整數(shù)轉(zhuǎn)成十六進(jìn)制表示 tmp = (Integer.toHexString(aB & 0XFF)); if (tmp.length() == 1) { sb.append("0"); } sb.append(tmp); } return sb.toString().toUpperCase(); // 轉(zhuǎn)成大寫 } // /** 將hex字符串轉(zhuǎn)換成字節(jié)數(shù)組 **/ private static byte[] hex2byte(String inputString) { if (inputString == null || inputString.length() < 2) { return new byte[0]; } inputString = inputString.toLowerCase(); int l = inputString.length() / 2; byte[] result = new byte[l]; for (int i = 0; i < l; ++i) { String tmp = inputString.substring(2 * i, 2 * i + 2); result[i] = (byte) (Integer.parseInt(tmp, 16) & 0xFF); } return result; } }
(8)ConstantUti.java
/** * 常量類 */ public class ConstantUtil { public static final int TIME_MILLIS = 5 * 1000;//連接超時(shí)時(shí)間 public static final int port = 25256;//端口號(hào) public static final String password = "123456885";//加密所使用的密鑰 public static final int CODE_TIMEOUT = 0;//連接超時(shí) public static final int CODE_SUCCESS = 1;//連接成功 public static final int CODE_UNKNOWN_HOST = 2;//錯(cuò)誤-未知的host }
(9)ToolUtil.java
import android.util.Log; import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; /** * 工具類 */ public class ToolUtil { /** * 獲取ip地址 * 如果是移動(dòng)網(wǎng)絡(luò),會(huì)顯示自己的公網(wǎng)IP,如果是局域網(wǎng),會(huì)顯示局域網(wǎng)IP * 因此本例中服務(wù)器端需要斷開移動(dòng)網(wǎng)絡(luò)以得到本機(jī)局域網(wǎng)IP */ public static String getHostIP() { String hostIp = null; try { Enumeration nis = NetworkInterface.getNetworkInterfaces(); InetAddress ia; while (nis.hasMoreElements()) { NetworkInterface ni = (NetworkInterface) nis.nextElement(); Enumeration<InetAddress> ias = ni.getInetAddresses(); while (ias.hasMoreElements()) { ia = ias.nextElement(); if (ia instanceof Inet6Address) { continue;// skip ipv6 } String ip = ia.getHostAddress(); if (!"127.0.0.1".equals(ip)) { hostIp = ia.getHostAddress(); break; } } } } catch (SocketException e) { Log.i("error", "SocketException"); e.printStackTrace(); } return hostIp; } /** * 判斷地址是否為IPV4地址 */ public static boolean IsIpv4(String ipv4) { if (ipv4 == null || ipv4.length() == 0) { return false;//字符串為空或者空串 } String[] parts = ipv4.split("\\.");//因?yàn)閖ava doc里已經(jīng)說明, split的參數(shù)是reg, 即正則表達(dá)式, 如果用"|"分割, 則需使用"\\|" if (parts.length != 4) { return false;//分割開的數(shù)組根本就不是4個(gè)數(shù)字 } for (String part : parts) { try { int n = Integer.parseInt(part); if (n < 0 || n > 255) { return false;//數(shù)字不在正確范圍內(nèi) } } catch (NumberFormatException e) { return false;//轉(zhuǎn)換數(shù)字不正確 } } return true; } }
(10)ToastUtil.java
import android.content.Context; import android.widget.Toast; public class ToastUtil { private static Toast mToast = null; /** * Toast方法 * * @param text 需要展示的文本 * @param context 所需上下文 */ public static void showToast(Context context, String text) { if (text != null) { if (mToast == null) { mToast = Toast.makeText(context, text, Toast.LENGTH_SHORT); } else { mToast.setText(text); mToast.setDuration(Toast.LENGTH_SHORT); } mToast.show(); } } }
3.權(quán)限及聲明
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <!--service部分--> <service android:name="com.test.test.LocalService"/>
代碼到此為止了,功能比較簡(jiǎn)單。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。
網(wǎng)站標(biāo)題:android基于socket的局域網(wǎng)內(nèi)服務(wù)器與客戶端加密通信
文章地址:http://muchs.cn/article6/pihcog.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供云服務(wù)器、網(wǎng)站設(shè)計(jì)公司、外貿(mào)網(wǎng)站建設(shè)、面包屑導(dǎo)航、App設(shè)計(jì)、網(wǎng)站策劃
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)