android加密的即时通信软件 -服务器端
16lz
2021-12-04
文章目录
- manifests
-
- AndroidManifest.xml
- java
-
- Activity
-
- BaseEventAcitivity
- Function_Socket_Server
- SQL
- Thread
-
- ListenThread
- ServerHandleSocketThread
- Util
-
- AESUtil
- ClientSocket
- ConstantUtil
- RSAUtil
- SRConstantsUtil
- ToolUtil
- res
-
- layout
-
- funtion_socket_server.xml
- values
-
- styles.xml
这是服务器端,整个通信软件客户端,服务器端源码包已经上传到我的资源。
manifests
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
java
Activity
BaseEventAcitivity
package com.example.socketserver.Activity;import android.os.Bundle;import android.view.Window;import androidx.appcompat.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); supportRequestWindowFeature(Window.FEATURE_NO_TITLE); getIntentData(); setContentView(getLayoutResId()); ButterKnife.bind(this);// 相当于 activity.subtitle = (TextView) activity.findViewById(R.id.subtitle); 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();}
Function_Socket_Server
package com.example.socketserver.Activity;import android.app.ProgressDialog;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.util.Log;import android.view.View;import android.widget.TextView;import android.widget.Toast;import com.example.socketserver.Thread.ListenThread;import com.example.socketserver.Util.AESUtil;import com.example.socketserver.Util.ConstantUtil;import com.example.socketserver.Service.LocalService;import com.example.socketserver.R;import com.example.socketserver.Util.ToolUtil;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 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; @BindView(R.id.edtTxt_server_Content) TextView edtTxt_server_Content; @BindView(R.id.edtTxt_server_clientAddress) TextView edtTxt_server_clientAddress; @Override protected int getLayoutResId() { return R.layout.function_socket_server; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); new ListenThread(ConstantUtil.port,Function_Socket_Server.this).start(); } @Override protected void init() { Log.d("Function_Socket_Server","init"); tv_localAddress.setText(ToolUtil.getHostIP());//获取本机局域网ip地址 } @OnClick({R.id.btn_startListener, R.id.btn_stopListener, R.id.btn_getUser,R.id.btn_server_encryptAndSend}) public void onClick(View v) { switch (v.getId()) { case R.id.btn_startListener://启动监听 break; case R.id.btn_stopListener://停止监听 break; case R.id.btn_getUser://刷新连接到此设备的IP并清空之前接收到的数据 ArrayList connectedIP = getConnectedIP(); StringBuilder resultList = new StringBuilder(); for (String ip : connectedIP) { resultList.append(ip); resultList.append("\n"); } Toast.makeText(Function_Socket_Server.this, "连接到手机上的Ip是"+ resultList.toString(), Toast.LENGTH_LONG).show(); tv_decryptContent.setText(""); tv_receivedContent.setText(""); break; case R.id.btn_server_encryptAndSend: Toast.makeText(Function_Socket_Server.this, "未实现功能", Toast.LENGTH_SHORT).show(); break; } } //订阅事件处理,处理 ListenThread 的 EventBus.getDefault().post(str); @Subscribe(threadMode = ThreadMode.MAIN)//在ui线程执行 public void getData(String data) { //dismissProgressDialog(); switch (data) { default: tv_receivedContent.append(data+"\n"); tv_decryptContent.append(AESUtil.decrypt(ConstantUtil.password, data)+"\n"); break; } } /** * 获取连接到本机热点上的手机ip */ private ArrayList getConnectedIP() { ArrayList connectedIP = new ArrayList<>(); try { //通过读取配置文件实现 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; }}
SQL
SQLiteHelper
package com.example.socketserver.SQL;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;public class SQLiteHelper extends SQLiteOpenHelper { //构造socket的数据库 public SQLiteHelper(Context context) { super(context, "socket.db", null, 1); } @Override public void onCreate(SQLiteDatabase db) { //创建一个名字为 information,3列的表格 //列:1: _id,2: USERNAME,3: PASSWORD db.execSQL("CREATE TABLE information(_id INTEGER PRIMARY KEY AUTOINCREMENT," + "USERNAME VARCHAR(20),PASSWORD VARCHAR(30),PRIVATEKEY VARCHAR(1250),PUBLICKEY VARCHAR(350))");//,LATESTIP VARCHAR(15) } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }}
Thread
ListenThread
package com.example.socketserver.Thread;import android.content.Context;import android.util.Log;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;/** * 监听线程 */public class ListenThread extends Thread { private ServerSocket serverSocket; private Context context; //构造函数,传递,端口,上下文 public ListenThread(int port, Context context) { try { serverSocket = new ServerSocket(port);//服务器端:创建绑定到指定 端口 的服务器套接字 } catch (IOException e) { e.printStackTrace(); } this.context = context; } @Override public void run() { Log.d("ListenThread","run"); while (true) {//不断得循环等待连接,读取数据 try { if (serverSocket != null) { Socket socket = serverSocket.accept();//调用accept()方法 等待客户连接 final String address = socket.getRemoteSocketAddress().toString();//获取发送客户端的地址 Log.d("ListenThread","new clients socket address:"+address); //每一个socket单独开启一个线程 ServerHandleSocketThread serverThread = new ServerHandleSocketThread(socket,context); serverThread.start(); } } catch (IOException e) { e.printStackTrace(); } } }}
ServerHandleSocketThread
package com.example.socketserver.Thread;import android.content.ContentValues;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.os.Build;import android.util.Log;import androidx.annotation.RequiresApi;import com.example.socketserver.SQL.SQLiteHelper;import com.example.socketserver.Util.AESUtil;import com.example.socketserver.Util.ClientSocket;import com.example.socketserver.Util.ConstantUtil;import com.example.socketserver.Util.RSAUtil;import com.example.socketserver.Util.SRConstantsUtil;import org.greenrobot.eventbus.EventBus;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.net.Socket;import java.security.NoSuchAlgorithmException;import java.util.Iterator;import java.util.Set;class ServerHandleSocketThread extends Thread{ private Socket socket; private Context context; private boolean exit = false; //在构造中得到要单独会话的socket public ServerHandleSocketThread(Socket socket, Context context) { this.socket = socket; this.context = context; } @RequiresApi(api = Build.VERSION_CODES.O) @Override public void run() { super.run(); if(!exit) while(true){ if(exit == true)break; try { InputStream inputStream = socket.getInputStream();//实现客户端和服务器端在线程上对话, 读取输入流 if (inputStream != null) { //读取接收到的数据 BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); String dataPacket = in.readLine();//读一行数据 //发送过来的数据不为空,判断数据内容 if (dataPacket != null) { String clientData = AESUtil.decrypt(ConstantUtil.password, dataPacket); int cmdBeginIndex1=clientData.indexOf(":")+1; int cmdEndIndex1 = clientData.indexOf("}"); String cmd=clientData.substring(cmdBeginIndex1,cmdEndIndex1); //登录, if (cmd.equals("login")) { Log.d("HandleSocketThread", "handle login"); //获取登录的用户名 int userNameBeginIndex = clientData.indexOf(":",cmdBeginIndex1) + 1; int userNameEndIndex = clientData.indexOf("}",userNameBeginIndex); String username = clientData.substring(userNameBeginIndex, userNameEndIndex); //获取登录的密码 int passwordBeginIndex = clientData.indexOf(":", userNameBeginIndex) + 1; int passwordEndIndex = clientData.indexOf("}", userNameEndIndex + 1); String password = clientData.substring(passwordBeginIndex, passwordEndIndex); SQLiteDatabase db; ContentValues values; SQLiteHelper helper = new SQLiteHelper(context); db = helper.getReadableDatabase(); //执行查询的SQL语句,查询账号,密码是否存在数据库中 //密码加密加密存储,所以得把得到的密码加密查询 Cursor cursor = db.rawQuery("select * from information where USERNAME=? and PASSWORD=?", new String[]{username, AESUtil.encrypt(ConstantUtil.password, password)}); //查无此数据,返回 if (cursor.getCount() == 0) { Log.d("HandleSocketThread", "login,无此用户数据"); //返回登录失败信息 writeResponse(socket, SRConstantsUtil.LOGIN_FAILED); socket.close(); exit = true; } //有此数据,准许登录 else if(cursor.getCount()!=0){ cursor.moveToFirst(); Log.d("HandleSocketThread ", "Login success "+"账号:" + cursor.getString(1) + "密码:" + cursor.getString(2)); Set keyset = ClientSocket.keySet(); Iterator it = keyset.iterator(); while (it.hasNext()) { String username1 = it.next(); if (username1.equals(username)) { //返回该账号已经登录信息 writeResponse(socket,SRConstantsUtil.LOGIN_ALREADY); cursor.close(); db.close(); return; } } ClientSocket.put(username,socket); Log.d("HandleSocketThread","add socket,clientSocketSize:"+String.valueOf(ClientSocket.size())); //返回登录成功信息 writeResponse(socket,SRConstantsUtil.LOGIN_SUCCESS); } cursor.close(); db.close(); } //连接通信,保持socket存在获取客户聊天使用的socket else if(cmd.equals("connect")){ Log.d("HandleSocketThread", "connect "); //获取登录的用户名 int userNameBeginIndex = clientData.indexOf(":",cmdBeginIndex1) + 1; int userNameEndIndex = clientData.indexOf("}",userNameBeginIndex); String username = clientData.substring(userNameBeginIndex, userNameEndIndex); //返回连接成功信息 writeResponse(socket,SRConstantsUtil.CONNECTSUCCESS); } //获得好友公钥 else if(cmd.equals("addFriend")){ //获取添加的好友的用户名 int userNameBeginIndex = clientData.indexOf(":",cmdBeginIndex1) + 1; int userNameEndIndex = clientData.indexOf("}",userNameBeginIndex); String frinedUsername = clientData.substring(userNameBeginIndex, userNameEndIndex); //查询数据库有无此数用户名 SQLiteDatabase db; ContentValues values; SQLiteHelper helper = new SQLiteHelper(context); db = helper.getReadableDatabase(); //执行查询的SQL语句 Cursor cursor = db.rawQuery("select * from information where USERNAME=? ", new String[]{frinedUsername}); //查无此数据,存储返回 if (cursor.getCount() == 0) { Log.d("HandleSocketThread", "no this frinedUsername "); //返回获取公钥错误 writeResponse(socket,SRConstantsUtil.NOFRIENDACCOUNT); } else { cursor.moveToFirst();//这句话一定要有,不然无法选中第一条!!!!! String publicKey = cursor.getString(4); if(publicKey != null){ Log.d("ServerThread", "发送公钥"); String publicKeyPacket = "{response:sendPublicKey}{key:"+publicKey+"}"; writeResponse(socket,publicKeyPacket); } } cursor.close(); db.close(); } //自己私钥 else if(cmd.equals("getPrivateKey")){ //{cmd:getPrivateKey}{username:"+username+"}" //获取登录的用户名 int userNameBeginIndex = clientData.indexOf(":",cmdBeginIndex1) + 1; int userNameEndIndex = clientData.indexOf("}",userNameBeginIndex); String username = clientData.substring(userNameBeginIndex, userNameEndIndex); //查询数据库有无此数用户名 SQLiteDatabase db; ContentValues values; SQLiteHelper helper = new SQLiteHelper(context); db = helper.getReadableDatabase(); //执行查询的SQL语句 Cursor cursor = db.rawQuery("select * from information where USERNAME=? ", new String[]{username}); //查无此数据,存储返回 if (cursor.getCount() == 0) { Log.d("HandleSocketThread", "get public key error"); //返回获取公钥错误 writeResponse(socket,SRConstantsUtil.GETPUBLICKEYERROR); } else { cursor.moveToFirst();//这句话一定要有,不然无法选中第一条!!!!! String privateKey = cursor.getString(3); Log.d("ServerThread", "发送私钥"); //返回注册失败信息 String publicKeyPacket = "{response:sendPrivateKey}{key:"+privateKey+"}"; writeResponse(socket,publicKeyPacket); } cursor.close(); db.close(); } //发送消息, else if (cmd.equals("sendMsg")) { Log.d("HandleSocketThread", "handle sendmsg"); boolean recIsOnline = false; //提取接收者账号 //{cmd:sendMsg}{receiverAccount:123}{msg:xxxx}{sender:xxx} int recBeginIndex=clientData.indexOf(":",cmdBeginIndex1)+1; int recIndex=clientData.indexOf("}", recBeginIndex); String recAccount=clientData.substring(recBeginIndex,recIndex); //根据接收者账号 遍历寻找是否在线 //判断登录存储的map中有 数据接收者账号 //有就从map中找到 相应接收者账号的socket,提取cilentData中的msg,并且发送消息出去给相应客户 //返回 发送者发送成功的消息,关闭发送者 发送数据的socket Set keyset = ClientSocket.keySet(); Iterator it = keyset.iterator(); while (it.hasNext()){ String username = it.next(); if(username.equals(recAccount)) { Log.d("HandleSocketThread","handle sendmsg,search and get recAccount:"+username); Log.d("HandleSocketThread","handle sendmsg,receiver is online "); recIsOnline = true; int msgBeginIndex=clientData.indexOf(":",recBeginIndex)+1; int msgIndex=clientData.indexOf("}", recIndex+1); String msg=clientData.substring(msgBeginIndex,msgIndex); int nextBeginIndex=clientData.indexOf("{",msgBeginIndex); int sendBeginIndex=clientData.indexOf(":",nextBeginIndex)+1; int sendIndex=clientData.indexOf("}", sendBeginIndex); String sendAccount=clientData.substring(sendBeginIndex,sendIndex); Log.d("HandleSocketThread","handle sendmsg,sendAccount is "+sendAccount+",now send "+msg+" to "+username); String msgPacket = "{response:transmit}{sender:"+sendAccount+"}{msg:"+msg+"}"; //根据keyset 找到 对应接收者的socket Socket socket1 = ClientSocket.get(username); writeResponse(socket1,msgPacket); Log.d("HandleSocketThread","handle sendmsg,msg has sent"); //返回发送成功信息 writeResponse(socket,SRConstantsUtil.MSGSEND_SUCCESS); //找到发送对象并且发送完毕,退出本次发送循环 break; } } //不在线,在线标志位 由遍历过程 改变 if(recIsOnline == false){ Log.d("HandleSocketThread","handle sendmsg,receiver isn't online "); //返回接收者不在线信息 writeResponse(socket,SRConstantsUtil.MSGSEND_FAILED_NOT_ONLINE); } exit = true; } //注册,关闭socket else if (cmd.equals("register")) { Log.d("HandleSocketThread", "handle register"); //获取注册的用户名 int userNameBeginIndex = clientData.indexOf(":",cmdBeginIndex1) + 1; int userNameEndIndex = clientData.indexOf("}",userNameBeginIndex); String username = clientData.substring(userNameBeginIndex, userNameEndIndex); //获取注册的密码 int passwordBeginIndex = clientData.indexOf(":", userNameBeginIndex) + 1; int passwordEndIndex = clientData.indexOf("}", userNameEndIndex + 1); String password = clientData.substring(passwordBeginIndex, passwordEndIndex); //查询数据库有无此数用户名 SQLiteDatabase db; ContentValues values; SQLiteHelper helper = new SQLiteHelper(context); db = helper.getReadableDatabase(); //执行查询的SQL语句 Cursor cursor = db.rawQuery("select * from information where USERNAME=? ", new String[]{username}); //查无此数据,存储返回 if (cursor.getCount() == 0) { Log.d("HandleSocketThread", "register,注册用户名无冲突"); db = helper.getWritableDatabase(); values = new ContentValues();//创建Contentvalues对象 values.put("USERNAME", username);//将数据添加到ContentValues对象 values.put("PASSWORD", AESUtil.encrypt(ConstantUtil.password, password)); RSAUtil.genKeyPair(); String publicKey = RSAUtil.getPublicKey(); String privateKey = RSAUtil.getPrivateKey(); values.put("PRIVATEKEY", privateKey); values.put("PUBLICKEY", publicKey); db.insert("information", null, values); Log.d("HandleSocketThread", "register,存储成功"); //返回注册成功信息 writeResponse(socket,SRConstantsUtil.REGISTER_SUCCESS); } else { Log.d("ServerThread", "注册用户名冲突"); //返回注册失败信息 writeResponse(socket,SRConstantsUtil.REGISTER_FAILED); } cursor.close(); db.close(); socket.close(); exit = true; } //用户退出APP消息,关闭socket,删除相应的map中的socket else if(cmd.equals("exitApp")) { Log.d("HandleSocketThread", "handle exist"); //{cmd:exitAPP}{username:123} int userNameBeginIndex=clientData.indexOf(":",cmdBeginIndex1)+1; int userNameEndIndex = clientData.indexOf("}",userNameBeginIndex); String username=clientData.substring(userNameBeginIndex,userNameEndIndex); ClientSocket.remove(username); Log.d("HandleSocketThread","handle exist,clientSocketSize:"+String.valueOf(ClientSocket.size())); //返回收到退出信息 writeResponse(socket,SRConstantsUtil.EXISTAPPNORMAL); socket.close(); exit = true; } else Log.d("HandleSocketThread","数据格式错误"); EventBus.getDefault().post(dataPacket);//发布事件,把获取到的信息显示出来 } } } catch (IOException | NoSuchAlgorithmException e) { e.printStackTrace(); } } } private void writeResponse(Socket socket,String response) throws IOException { OutputStream outputStream = socket.getOutputStream(); OutputStreamWriter opsw = new OutputStreamWriter(outputStream);// BufferedWriter writer = new BufferedWriter(opsw); writer.write(AESUtil.encrypt(ConstantUtil.password, response)+ "\r\n\r\n");//由于socket使用缓冲区进行读写数据,因此使用\r\n\r\n用于表明数据已写完.不加这个会导致数据无法发送 writer.flush(); }}
Util
AESUtil
package com.example.socketserver.Util;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加密,不需要设置IV,但是不安全 private static final String CipherMode = "AES/CFB/NoPadding";//使用CFB加密,需要设置IV;CFB(Cipher FeedBack Mode,加密反馈),不填充 /** * 生成加密后的密钥 * * @param password 密钥种子 * @return isSucceed */ private static SecretKeySpec createKey(String password) { byte[] data = null; if (password == null) { password = ""; } StringBuilder sb = new StringBuilder(32);//32位容量的字符串 sb.append(password);//字符串追加密码 while (sb.length() < 32) { sb.append("0");//少于32位,追加‘0’ } if (sb.length() > 32) { //setLength(newLength) //如果 newLength 参数小于当前长度,则长度将更改为指定的长度。 //如果 newLength 参数大于或等于当前长度,则将追加有效的 null 字符 ('u0000'),使长度满足 newLength 参数。 sb.setLength(32); } try { data = sb.toString().getBytes("UTF-8");//得到 使用UTF-8编码表 的一个系统默认的编码格式的 字节数组 } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return new SecretKeySpec(data, "AES");//根据32字节的数据,生成一个AES算法生成的密钥 } // /** 加密字节数据 **/ private static byte[] encrypt(byte[] content, String password) { try { SecretKeySpec key = createKey(password);//根据密钥种子生成密钥 System.out.println(key); Cipher cipher = Cipher.getInstance(CipherMode); //初始化Cipher,mode指定是加密还是解密,key为公钥或密钥;ENCRYPT_MODE加密模式, // 实例化IvParameterSpec对象,使用指定的初始化向量 cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec( new byte[cipher.getBlockSize()])); //使用CFB加密CFB(Cipher FeedBack Mode,加密反馈)、不填充的方式 //init为 加密形式 //返回btye[]数组 return cipher.doFinal(content); } catch (Exception e) { e.printStackTrace(); } return null; } // /** 加密(结果为16进制字符串) **/ public static String encrypt(String password, String content) { Log.d("加密前", "seed=" + password + "\ncontent=" + content); byte[] data = null;//byte字节数组 try { data = content.getBytes("UTF-8"); } catch (Exception e) { e.printStackTrace(); } data = encrypt(data, password);//加密字节数据 String result = byte2hex(data);//字节转hex Log.d("加密后", "result=" + result); return result; } // /** 解密字节数组 **/ 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进制的字符串为字符串 **/ 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; } // /** 字节数组转成16进制字符串 **/ private static String byte2hex(byte[] b) { // 一个字节的数, StringBuilder sb = new StringBuilder(b.length * 2); String tmp ; for (byte aB : b) { // 整数转成十六进制表示 tmp = (Integer.toHexString(aB & 0XFF)); if (tmp.length() == 1) { sb.append("0"); } sb.append(tmp); } return sb.toString().toUpperCase(); // 转成大写 } // /** 将hex字符串转换成字节数组 **/ 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; }}
ClientSocket
package com.example.socketserver.Util;import java.net.Socket;import java.util.HashMap;import java.util.Set;public class ClientSocket { private static HashMap clients = new HashMap();// 创建一个集合存放所有的客户端 的用户名,和客户socket public static void put(String username, Socket userSocket){ clients.put(username,userSocket); } public static int size() { return clients.size(); } public static Socket get(String username) { return clients.get(username); } public static void remove(String username) { clients.remove(username); } public static Set keySet() { return clients.keySet(); }}
ConstantUtil
package com.example.socketserver.Util;/** * 常量类 */public class ConstantUtil { public static final int TIME_MILLIS = 5 * 1000;//连接超时时间 public static final int port = 25256;//端口号 public static final String password = "123456885";//加密所使用的密钥 public static final String CODE_TIMEOUT = "pzl0";//连接超时 public static final String CODE_SUCCESS = "pzl1";//连接成功 public static final String CODE_UNKNOWN_HOST = "pzl2";//错误-未知的host public static final String SERVERIP = "SERVERIP";//服务器地址}
RSAUtil
package com.example.socketserver.Util;import android.os.Build;import androidx.annotation.RequiresApi;import java.util.Base64;import javax.crypto.Cipher;import java.security.KeyFactory;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.HashMap;import java.util.Map;public class RSAUtil { /** * 密钥长度 于原文长度对应 以及越长速度越慢 */ private final static int KEY_SIZE = 1536; private static final String CipherMode = "RSA"; /** * 用于封装随机产生的公钥与私钥 */ private static Map keyMap = new HashMap(); //公钥 public static final String PUBLIC_KEY = "RSAPublicKey"; //私钥 public static final String PRIVATE_KEY = "RSAPrivateKey"; /** * 随机生成密钥对 */ @RequiresApi(api = Build.VERSION_CODES.O) public static void genKeyPair() throws NoSuchAlgorithmException { // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(CipherMode); // 初始化密钥对生成器 keyPairGen.initialize(KEY_SIZE, new SecureRandom()); // 生成一个密钥对,保存在keyPair中 KeyPair keyPair = keyPairGen.generateKeyPair(); // 得到私钥 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到公钥 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded()); // 得到私钥字符串 String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded()); // 将公钥和私钥保存到Map //0表示公钥 keyMap.put(PUBLIC_KEY, publicKeyString); //1表示私钥 keyMap.put(PRIVATE_KEY, privateKeyString); } public static String getPublicKey(){ return keyMap.get(PUBLIC_KEY); } public static String getPrivateKey(){ return keyMap.get(PRIVATE_KEY); } /** * RSA公钥加密 * * @param str 加密字符串 * @param publicKey 公钥 * @return 密文 * @throws Exception 加密过程中的异常信息 */ @RequiresApi(api = Build.VERSION_CODES.O) public static String encrypt(String str, String publicKey) throws Exception { //base64编码的公钥 byte[] decoded = Base64.getDecoder().decode(publicKey); RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance(CipherMode).generatePublic(new X509EncodedKeySpec(decoded)); //RSA加密 Cipher cipher = Cipher.getInstance(CipherMode); cipher.init(Cipher.ENCRYPT_MODE, pubKey); String outStr = Base64.getEncoder().encodeToString(cipher.doFinal(str.getBytes("UTF-8"))); return outStr; } /** * RSA私钥解密 * * @param str 加密字符串 * @param privateKey 私钥 * @return 明文 * @throws Exception 解密过程中的异常信息 */ public static String decrypt(String str, String privateKey) throws Exception { //64位解码加密后的字符串 byte[] inputByte = Base64.getDecoder().decode(str); //base64编码的私钥 byte[] decoded = Base64.getDecoder().decode(privateKey); RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance(CipherMode).generatePrivate(new PKCS8EncodedKeySpec(decoded)); //RSA解密 Cipher cipher = Cipher.getInstance(CipherMode); cipher.init(Cipher.DECRYPT_MODE, priKey); String outStr = new String(cipher.doFinal(inputByte)); return outStr; }}
SRConstantsUtil
package com.example.socketserver.Util;public class SRConstantsUtil { public static final String REGISTER_SUCCESS = "{response:register_success}";//注册成功 public static final String REGISTER_FAILED = "{response:register_failed}";//注册失败 public static final String LOGIN_SUCCESS = "{response:login_success}";//登录成功 public static final String LOGIN_FAILED = "{response:login_failed}";//登录识别 public static final String LOGIN_ALREADY = "{response:login_already}";//登录识别 public static final String MSGSEND_SUCCESS = "{response:send_msg_success}";//连接成功 public static final String MSGSEND_FAILED = "{response:send_msg_failed}";//连接成功 public static final String MSGSEND_FAILED_NOT_ONLINE = "{response:receiver_not_online}";//接收者不在线 public static final String MSGSEND_FAILED_NOT_EXIST = "{response:receiver_not_exist}";//接收者错误 public static final String EXISTAPPNORMAL = "{response:exist_normal}";//退出成功 public static final String EXISTAPPABNORMAL = "{response:exist_abnormal}";//退出错误 public static final String CONNECTSUCCESS = "{response:connect_success}";//连接成功 public static final String NOFRIENDACCOUNT = "{response:no_user_account}";//没有此好友用户 public static final String GETPUBLICKEYERROR = "{response:get_privateKey_error}";//获取公钥错误 //public static final String PRIVATEKEY = "{response:privateKey}{key:";//获取公钥错误}
ToolUtil
package com.example.socketserver.Util;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地址 * 如果是移动网络,会显示自己的公网IP,如果是局域网,会显示局域网IP * 因此本例中服务器端需要断开移动网络以得到本机局域网IP */ public static String getHostIP() { String hostIp = null; try { Enumeration nis = NetworkInterface.getNetworkInterfaces(); InetAddress ia; while (nis.hasMoreElements()) { NetworkInterface ni = (NetworkInterface) nis.nextElement(); Enumeration 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("\\.");//因为java doc里已经说明, split的参数是reg, 即正则表达式, 如果用"|"分割, 则需使用"\\|" if (parts.length != 4) { return false;//分割开的数组根本就不是4个数字 } for (String part : parts) { try { int n = Integer.parseInt(part); if (n < 0 || n > 255) { return false;//数字不在正确范围内 } } catch (NumberFormatException e) { return false;//转换数字不正确 } } return true; }}
res
layout
funtion_socket_server.xml
<?xml version="1.0" encoding="utf-8"?>
values
styles.xml
gradle与客户端一样
更多相关文章
- Android(安卓)JSON,Gson,fastjson实现比较
- ch020 Android(安卓)SQLite3(第二部分)
- ch020 Android(安卓)SQLite3(第二部分)
- Android漏洞——将Android恶意代码隐藏在图片中
- 第三课:android数据相关---文件
- Android(安卓)Media (Audio) Framework Analyse
- [Android(安卓)Develop_003]-Android(安卓)Database
- android中的数据库操作
- struts2服务端与android交互