Android Socket通信

亦余心之所善兮,虽九死其犹未悔。这篇文章主要讲述Android Socket通信相关的知识,希望能为你提供帮助。
目标Demo是通过java ServerSocket 和 Socket 通信实现客户端发送消息和发送文件到服务器,服务器接收到消息和文件,并且实现解决inputStream.read()的阻塞问题思路。
服务器端 创建ServerSocket服务器

serverSocket = new ServerSocket(port); //首先创建一个服务端口 //等待客户端的连接请求 socket = serverSocket.accept();

等待Socket客户端连接
//等待客户端的连接请求 socket = serverSocket.accept(); final String socketAddress = socket.getRemoteSocketAddress().toString(); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(ServerActivity.this, "成功建立与客户端的连接 : " + socketAddress, Toast.LENGTH_SHORT).show(); Log.i("Lin", "成功建立与客户端的连接 : " + socketAddress); } });

接收Socket客户端信息为了防止接收消息时,服务器inputStream.read()读取消息时产生阻塞,以换行符(" " )结束inputStream.read()
byte[] bytes = new byte[1]; StringBuilder info = new StringBuilder(); while (inputStream.read(bytes) != -1) { String str = new String(bytes); if (str.equals(" ")) { break; } info.append(new String(bytes)); } final String finalInfo = info.toString(); Log.i("Lin", "text = " + finalInfo); runOnUiThread(new Runnable() { @Override public void run() { mEtReceive.setText(mEtReceive.getText().toString() + socketAddress + " : " + finalInfo + " "); } });

接收Socket客户端文件为了防止接收消息时,服务器inputStream.read()接受文件时产生阻塞,以文件MD5校验码进行校验,从而结束inputStream.read()
byte[] remote = new byte[32]; String md5 = ""; if (inputStream.read(remote) != -1) { md5 = nullOfString(new String(remote)); }final String root = Environment.getExternalStorageDirectory().getPath(); Log.i("Lin", root); byte[] inputByte = new byte[1024 * 1024]; int len = 0; long fileSize = 0; DataInputStream dis = new DataInputStream(inputStream); // 文件名和长度 String fileName = dis.readUTF(); final long fileLength = dis.readLong(); Log.i("Lin", "fileName = " + fileName); Log.i("Lin", "fileLength = " + fileLength); mPath = root + "/ECG/" + fileName; File file = new File(root + "/ECG/"); if (!file.exists()) file.mkdir(); file = new File(mPath); FileOutputStream fileOutputStream = new FileOutputStream(file); String fileMD5 = nullOfString(getFileMD5(new File(mPath))); while (!md5.equals(fileMD5) & & (len = dis.read(inputByte, 0, inputByte.length)) > 0) { fileSize += len; fileOutputStream.write(inputByte, 0, len); fileOutputStream.flush(); fileMD5 = nullOfString(getFileMD5(new File(mPath))); Log.i("Lin", "md5 = " + md5 + " file = " + fileMD5); Log.i("Lin", "fileLength = " + fileLength + " fileSize = " + fileSize + " " + (fileSize * 100 / fileLength) + "%") ; final long finalFileSize = fileSize; runOnUiThread(new Runnable() { @Override public void run() { mProgressDialog.setMessage((finalFileSize * 100 / fileLength) + "%"); mProgressDialog.show(); } }); if (md5.equals(fileMD5)) { fileOutputStream.close(); runOnUiThread(new Runnable() { @Override public void run() { mProgressDialog.hide(); } }); } } Log.i("Lin", "md52 = " + md5 + " file2 = " + getFileMD5(file)); fileMD5 = nullOfString(getFileMD5(new File(mPath))); Log.i("Lin", "file = " + fileMD5); final String finalFileMD = fileMD5; final String finalMd = md5; runOnUiThread(new Runnable() { @Override public void run() { mEtReceive.setText(mEtReceive.getText().toString() + "文件路径:" + mPath + " "); mEtReceive.setText(mEtReceive.getText().toString() + "file = " + finalFileMD + " "); mEtReceive.setText(mEtReceive.getText().toString() + "text = " + finalMd + " "); } });

客户端 创建Socket客户端 连接ServerSocket服务器
socket = new Socket(); socket.connect(new InetSocketAddress(ip, port)); //ip= 服务器ip //port= 服务器端口

向ServerSocket服务器发送消息
try { if (socket == null) return; OutputStream om = socket.getOutputStream(); om.write(Constant.SERVER_TEXT.getBytes()); om.write(returnServer.getBytes()); om.write(" ".getBytes()); //[10] om.flush(); } catch (Exception e) { e.printStackTrace(); Log.i("Lin", e.toString()); }

为了防止发送消息时,服务器inputStream.read()读取消息时产生阻塞,客户端以换行符结束发送(om.write(" " .getBytes()); )
向ServerSocket服务器发送文件
File file = new File(finalImagePath); if (file.exists()) { final String fileMD5 = nullOfString(getFileMD5(file)); OutputStream outputStream = socket.getOutputStream(); runOnUiThread(new Runnable() { @Override public void run() { mEtReceive.setText(mEtReceive.getText().toString() + "file = " + fileMD5 + " "); } }); FileInputStream fileInputStream = new FileInputStream(file); outputStream.write(Constant.SERVER_FILE.getBytes()); outputStream.flush(); outputStream.write(fileMD5.getBytes()); outputStream.flush(); DataOutputStream dis = new DataOutputStream(outputStream); // 文件名和长度 dis.writeUTF(file.getName()); dis.flush(); dis.writeLong(file.length()); dis.flush(); byte[] buffer = new byte[1024 * 1024]; int len = 0; while ((len = fileInputStream.read(buffer, 0, buffer.length)) > 0) { dis.write(buffer, 0, len); dis.flush(); } fileInputStream.close(); Log.i("Lin", "传输成功"); }

【Android Socket通信】为了防止发送文件时,服务器inputStream.read()接受文件时产生阻塞,客户端先向服务器发送文件MD5校验码再发送文件,服务器对接收文件进行校验从而结束inputStream.read()阻塞。
Demo中发送格式 字符:SERVER_TEXT + 字符 + 换行符( ) 文件:SERVER_FILE + 文件MD5校验码 + 文件 获取文件MD5
private static String getFileMD5(File file) { if (!file.isFile()) { return null; } MessageDigest digest; FileInputStream in; try { byte[] buffer = new byte[1024]; int len; digest = MessageDigest.getInstance("MD5"); in = new FileInputStream(file); while ((len = in.read(buffer, 0, 1024)) != -1) { digest.update(buffer, 0, len); } in.close(); BigInteger bigInt = new BigInteger(1, digest.digest()); return bigInt.toString(16); } catch (Exception e) { e.printStackTrace(); return null; } }

GitHub THE END

    推荐阅读