实现了基本的socket通信(即两台设备,一台用作服务器,一台用作客户端),服务器进行监听,客户端发送加密数据到服务器,服务器进行解密得到明文。
注意:本项目中使用了ButterKnife及EventBus作为辅助工具,通信建立时默认网络正常(未做局域网网络环境检测),加密方式为AES加密
1.效果图:
(1)客户端
(2)服务器端
2.界面布局部分
(1)服务器端布局 function_socket_server.xml
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout style="@style/ToolBar">
<TextView
style="@style/ToolBar_tv_Title"
android:text="网络加密-服务器端"/>
</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="启动监听"/>
<Button
android:id="@+id/btn_stopListener"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="停止监听"/>
<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="本机地址:"/>
<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
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout style="@style/ToolBar">
<TextView
style="@style/ToolBar_tv_Title"
android:text="网络加密-客户端"/>
</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="服务器地址:"/>
<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="文本内容:"
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="加密并发送"/>
</LinearLayout>
(3)用到的style
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22<!--通用Title的右侧按钮-->
<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
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import org.greenrobot.eventbus.EventBus;
import butterknife.ButterKnife;
public abstractclassBaseEventActivity extendsAppCompatActivity {
@Override
publicvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getIntentData();
setContentView(getLayoutResId());
ButterKnife.bind(this);
EventBus.getDefault().register(this);
init();
}
protectedvoid getIntentData() {
}
@Override
protectedvoid onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
protectedabstract voidinit();
protectedabstract intgetLayoutResId();
}
(2)服务器主界面 Function_Socket.java
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126import 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;
/**
* 服务器界面
*/
public classFunction_Socket_Server extendsBaseEventActivity {
@BindView(R.id.tv_localAddress)
TextView tv_localAddress;
@BindView(R.id.tv_receivedContent)
TextView tv_receivedContent;
@BindView(R.id.tv_decryptContent)
TextView tv_decryptContent;
privateLocalService localService;//用于启动监听的服务
privateServiceConnection sc;//服务连接
@Override
protectedvoid init() {
tv_localAddress.setText(ToolUtil.getHostIP());
sc = newServiceConnection() {
@Override
publicvoidonServiceConnected(ComponentName name, IBinder service) {
LocalService.LocalBinder localBinder = (LocalService.LocalBinder) service;
localService = localBinder.getService();
localService.startWaitDataThread();
ToastUtil.showToast(Function_Socket_Server.this, "监听已启动");
}
@Override
publicvoidonServiceDisconnected(ComponentName name) {
}
};
connection();
}
@Subscribe(threadMode = ThreadMode.MAIN)
publicvoidgetData(String data) {
tv_receivedContent.setText(data);
tv_decryptContent.setText(AESUtil.decrypt(ConstantUtil.password, data));
}
/**
* 绑定service
*/
privatevoidconnection() {
Intent intent = new Intent(this, LocalService.class);
bindService(intent, sc, BIND_AUTO_CREATE);
}
@Override
protectedint getLayoutResId() {
returnR.layout.function_socket_server;
}
/**
* 获取连接到本机热点上的手机ip
*/
privateArrayList<String> getConnectedIP() {
ArrayList<String> connectedIP = newArrayList<>();
try{
//通过读取配置文件实现
BufferedReader br = newBufferedReader(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();
}
returnconnectedIP;
}
@OnClick({R.id.btn_startListener, R.id.btn_stopListener, R.id.btn_getUser})
publicvoidonClick(View v) {
switch(v.getId()) {
caseR.id.btn_startListener://启动监听
connection();
break;
caseR.id.btn_stopListener://停止监听
if(sc != null)
unbindService(sc);
break;
caseR.id.btn_getUser://刷新连接到此设备的IP并清空之前接收到的数据
ArrayList<String> connectedIP = getConnectedIP();
StringBuilder resultList = newStringBuilder();
for(String ip : connectedIP) {
resultList.append(ip);
resultList.append("
");
}
ToastUtil.showToast(this, "连接到手机上的Ip是:"+ resultList.toString());
tv_decryptContent.setText("");
tv_receivedContent.setText("");
break;
}
}
publicvoidonDestroy() {
super.onDestroy();
if(sc != null)
unbindService(sc);
}
}