1 前言

使用Socket实现跨设备通讯 中介绍了使用 WiFi 通道实现跨设备通讯,本文将介绍使用 Bluetooth 通道实现跨进程通讯。

​ 本文全部代码见→使用BluetoothSocket实现跨设备通讯

1.1 蓝牙通讯核心类

​ 在蓝牙通讯中,主要用到 BluetoothAdapter、BluetoothDevice、BluetoothServerSocket、BluetoothSocket。

(1)BluetoothAdapter(管理本机蓝牙设备)

public static synchronized BluetoothAdapter getDefaultAdapter() //获取默认的蓝牙适配器对象

public boolean isEnabled() //判断蓝牙功能是否打开
public boolean enable() //打开蓝牙功能(不会弹出提示)
public boolean disable() //关闭蓝牙功能 public boolean isDiscovering() //判断当前是否正在搜索设备
public boolean startDiscovery() //搜索周围的蓝牙设备,结果通过广播返回
public boolean cancelDiscovery() //取消搜索 public Set<BluetoothDevice> getBondedDevices() //获取本机已绑定的设备列表
public BluetoothDevice getRemoteDevice(String address) //根据蓝牙地址获取远程的蓝牙设备 public boolean setName(String name) // 设置本机蓝牙名称
public String getName() // 获取本机蓝牙名称 public String getAddress() //获取本机蓝牙地址 // 创建并返回 BluetoothServerSocket
public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid) //不安全的
public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid) //安全的

(2)BluetoothDevice(管理对端蓝牙设备)

public String getName() //获取远程设备名称
public String getAddress() //获取远程设备地址 //创建并返回 BluetoothSocket
public BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUID uuid) //非安全的
public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) //安全的

(3)BluetoothServerSocket

public BluetoothSocket accept() //服务端监听外部的蓝牙连接请求(会阻塞当前线程,建议在子线程中执行)
public void close() //关闭服务端的蓝牙监听

(4)BluetoothSocket

public void connect() //建立蓝牙 Socket 连接(客户端调用)
public void close() //关闭蓝牙 Socket 连接 public BluetoothDevice getRemoteDevice() //获取远程蓝牙设备 public InputStream getInputStream() //获取 Socket 连接的输入流对象
public OutputStream getOutputStream()//获取 Socket 连接的输出流对象

1.2 蓝牙通讯基本流程

(1)权限申请

<!-- 蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
<!-- 位置访问权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

(2)服务端接口调用

//获取 BluetoothSocket
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
mServerSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord("server_name", UUID.fromString(UUIDString))
mSocket = mServerSocket.accept() //调用此方法会阻塞当前线程,建议在子线程中执行 // 读取对端数据
in = mSocket.getInputStream()
byte[] bt = new byte[50]
in.read(bt) // 向对端发送数据
out = new PrintWriter(mSocket.getOutputStream())
out.print(content)
out.flush()

(3)客户端接口调用

// 发现设备
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
mBluetoothAdapter.startDiscovery()
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case BluetoothDevice.ACTION_FOUND: //接收搜索到的蓝牙设备
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
list.add(device);
break;
}
}
} //获取 BluetoothSocket,并建立蓝牙 Socket 连接
remoteDevice = mBluetoothAdapter.getRemoteDevice(remoteAddress);
mSocket = remoteDevice.createRfcommSocketToServiceRecord(UUID.fromString(UUIDString));
mSocket.connect() //调用此方法会阻塞当前线程,建议在子线程中执行 // 读取对端数据
in = mSocket.getInputStream()
byte[] bt = new byte[50]
in.read(bt) // 向对端发送数据
out = new PrintWriter(mSocket.getOutputStream())
out.print(content)
out.flush()

2 项目结构

​ 说明:客户端(bluetooth_c )中 discover 包里的类用于搜索蓝牙设备。

3 服务端(bluetooth_S)

​ BluetoothService.java

package com.zhyan8.bluetooth_s;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.os.Handler;
import android.os.Message;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.UUID; public class BluetoothService {
final String UUIDString = "00001101-0000-1000-8000-00805F9B34FB";
private Handler mHandler;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothServerSocket mServerSocket;
private BluetoothSocket mSocket;
private InputStream in;
private PrintWriter out;
private Object lock = new Object(); BluetoothService(Handler handler) {
mHandler = handler;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
try {
mServerSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord("server_name", UUID.fromString(UUIDString));
} catch (IOException e) {
e.printStackTrace();
}
} private void connect(){
new Thread() {
@Override
public void run() {
try {
synchronized (lock) {
if (mSocket!=null) {
return;
}
mSocket = mServerSocket.accept(); // 会阻塞线程,建议在子线程中进行
in = mSocket.getInputStream();
out = new PrintWriter(mSocket.getOutputStream());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
} public void begin_listen() {
while (mSocket==null) {
connect();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
new Thread() {
@Override
public void run() {
try {
while (mSocket.isConnected()) {
byte[] bt = new byte[50];
in.read(bt);
String content = new String (bt, "UTF-8" );
if (content!=null && !content.equals("")) {
Message msg = new Message();
msg.obj = content;
mHandler.sendMessage(msg);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
} public void send_msg(final String content) {
new Thread() {
@Override
public void run() {
out.print(content);
out.flush ();
}
}.start();
}
}

​ ChatActivity.java

package com.zhyan8.bluetooth_s;

import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView; public class ChatActivity extends AppCompatActivity {
private BluetoothService service;
private EditText et_msg;
private TextView tv_msg; public static final String[] permissions = {
"android.permission.BLUETOOTH",
"android.permission.BLUETOOTH_ADMIN",
"android.permission.ACCESS_COARSE_LOCATION",
"android.permission.BLUETOOTH_PRIVILEGED" }; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
if(Build.VERSION.SDK_INT>=23){
requestPermissions(permissions,1);
}
init();
} private void init() {
et_msg = (EditText) findViewById(R.id.et_msg);
tv_msg = (TextView) findViewById(R.id.tv_msg);
service = new BluetoothService(mHandler);
service.begin_listen();
} public void onClick(View v) { //单击发送按钮
String content = et_msg.getText().toString().trim();
if (content!=null && !content.equals("")) {
service.send_msg(content);
}
} private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
String content = (String) msg.obj;
tv_msg.setText(content);
}
};
}

​ activity_chat.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.zhyan8.bluetooth_s.ChatActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="接收的消息:"
android:textSize="20sp"
android:gravity="center_vertical"/>
<TextView
android:id="@+id/tv_msg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"
android:gravity="center_vertical"/>
</LinearLayout> <EditText
android:id="@+id/et_msg"
android:layout_width="match_parent"
android:layout_height="100dp"
android:textSize="30sp"
android:background="#ffcc66"/> <Button
android:id="@+id/btn_send"
android:layout_width="match_parent"
android:layout_height="80dp"
android:text="发送"
android:textSize="30sp"
android:layout_marginTop="30dp"
android:onClick="onClick"/>
</LinearLayout>

​ 界面如下:

4 客户端(bluetooth_C)

4.1 搜索设备

​ ScanDevices.java

package com.zhyan8.bluetooth_c.discover;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set; public class ScanDevices {
private BluetoothAdapter mBluetoothAdapter; ScanDevices() {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
} public ArrayList<BluetoothDevice> getBondedDevices() { //获取已绑定设备列表
Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
ArrayList bondedDevices = new ArrayList();
Iterator<BluetoothDevice> iterator = devices.iterator();
while (iterator.hasNext()) {
bondedDevices.add(iterator.next());
}
return bondedDevices;
} public void startDiscovery() { //搜索周围蓝牙设备,并通过广播返回
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable(); // 打开蓝牙功能
return;
}
mBluetoothAdapter.startDiscovery();
}
}

​ DeviceAdapter.java

package com.zhyan8.bluetooth_c.discover;

import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import com.zhyan8.bluetooth_c.R;
import java.util.ArrayList; public class DevicesAdapter extends BaseAdapter { private ArrayList<BluetoothDevice> list;
private Context mContext; public DevicesAdapter(Context context, ArrayList<BluetoothDevice> list){
mContext = context;
this.list = list;
} @Override
public int getCount() {
return list.size();
} @Override
public Object getItem(int position) {
return list.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.device_list, null);
ViewHolder viewHolder = new ViewHolder(convertView);
BluetoothDevice device = list.get(position);
viewHolder.name.setText(device.getName());
viewHolder.mac.setText(device.getAddress());
return convertView;
} public class ViewHolder{
private TextView name;
private TextView mac;
public ViewHolder(View view){
name = (TextView) view.findViewById(R.id.device_name);
mac = (TextView) view.findViewById(R.id.device_mac);
}
}
}

​ device_list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"> <TextView
android:id="@+id/device_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp"
android:textColor="#FF0000FF"/> <TextView
android:id="@+id/device_mac"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingBottom="10dp"
android:textColor="#808080"/>
</LinearLayout>

​ MainActivity.java

package com.zhyan8.bluetooth_c.discover;

import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import com.zhyan8.bluetooth_c.ChatActivity;
import com.zhyan8.bluetooth_c.R;
import java.util.ArrayList; public class MainActivity extends AppCompatActivity {
private ListView listView;
private DevicesAdapter adapter;
private ArrayList<BluetoothDevice> list;
private ScanDevices mScanDevices; public static final String[] permissions = {
"android.permission.BLUETOOTH",
"android.permission.BLUETOOTH_ADMIN",
"android.permission.ACCESS_COARSE_LOCATION",
"android.permission.BLUETOOTH_PRIVILEGED" }; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(Build.VERSION.SDK_INT>=23){
requestPermissions(permissions,1);
}
init();
} private void init() {
listView = (ListView) findViewById(R.id.listview);
list = new ArrayList<>();
adapter = new DevicesAdapter(this, list);
listView.setAdapter(adapter);
listView.setOnItemClickListener(icl);
mScanDevices = new ScanDevices();
initReceiver();
} private void initReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
registerReceiver(receiver, filter);
} public void onClick(View view){ //单击扫描按钮
list.clear();
list.addAll(mScanDevices.getBondedDevices()); //添加已绑定的设备列表
adapter.notifyDataSetChanged();
mScanDevices.startDiscovery(); //搜索周围蓝牙设备,并通过广播返回
} BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case BluetoothDevice.ACTION_FOUND: //接收搜索到的蓝牙设备
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String address = device.getAddress();
for (int i = 0; i < list.size(); i++) { //避免接收重复的设备
if (address == null || address.equals(list.get(i).getAddress())) {
return;
}
}
list.add(device);
adapter.notifyDataSetChanged();
break;
}
}
}; AdapterView.OnItemClickListener icl = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String address = list.get(position).getAddress();
startChat(address);
}
}; private void startChat(String remoteAddress) {
Intent intent = new Intent(this, ChatActivity.class);
intent.putExtra("remoteAddress", remoteAddress);
startActivity(intent);
} @Override
protected void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
}

​ activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".discover.MainActivity"> <Button
android:id="@+id/scan_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="扫描"/> <ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</LinearLayout>

4.2 设备通讯

​ BluetoothClient.java

package com.zhyan8.bluetooth_c;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Handler;
import android.os.Message;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.UUID; public class BluetoothClient {
final String UUIDString = "00001101-0000-1000-8000-00805F9B34FB";
private Handler mHandler;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothSocket mSocket;
private InputStream in;
private PrintWriter out;
private Object lock = new Object(); BluetoothClient(Handler handler, String remoteAddress) {
mHandler = handler;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice remoteDevice = mBluetoothAdapter.getRemoteDevice(remoteAddress);
try {
mSocket = remoteDevice.createRfcommSocketToServiceRecord(UUID.fromString(UUIDString));
} catch (IOException e) {
e.printStackTrace();
}
} private void connect(){
new Thread() {
@Override
public void run() {
try {
synchronized (lock) {
if (mSocket.isConnected()) {
return;
}
mSocket.connect(); // 会阻塞线程,建议在子线程中进行
in = mSocket.getInputStream();
out = new PrintWriter(mSocket.getOutputStream());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
} public void begin_listen() {
while (!mSocket.isConnected()) {
connect();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
new Thread() {
@Override
public void run() {
try {
while (mSocket.isConnected()) {
byte[] bt = new byte[50];
in.read(bt);
String content = new String (bt, "UTF-8" );
if (content!=null && !content.equals("")) {
Message msg = new Message();
msg.obj = content;
mHandler.sendMessage(msg);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
} public void send_msg(final String content) {
new Thread() {
@Override
public void run() {
out.print(content);
out.flush ();
}
}.start();
}
}

​ ChatActivity.java

package com.zhyan8.bluetooth_c;

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView; public class ChatActivity extends AppCompatActivity {
private BluetoothClient client;
private EditText et_msg;
private TextView tv_msg; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
init();
} private void init() {
et_msg = (EditText) findViewById(R.id.et_msg);
tv_msg = (TextView) findViewById(R.id.tv_msg);
Intent intent = getIntent();
String remoteAddress = intent.getStringExtra("remoteAddress");
client = new BluetoothClient(mHandler, remoteAddress);
client.begin_listen();
} public void onClick(View v) { //单击发送按钮
String content = et_msg.getText().toString().trim();
if (content!=null && !content.equals("")) {
client.send_msg(content);
}
} private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
String content = (String) msg.obj;
tv_msg.setText(content);
}
};
}

​ activity_chat.xml

​ 同第3节。

5 效果展示

​ 客户端:

​ 点击第一个设备,进入会话界面:

​ 服务端:

​ 声明:本文转自【Android】使用BluetoothSocket实现跨设备通讯

【Android】使用BluetoothSocket实现跨设备通讯的更多相关文章

  1. AllJoyn+Android开发案例-android跨设备调用方法

    AllJoyn+Android开发案例-android跨设备调用方法 项目须要涉及AllJoyn开源物联网框架.前面主要了解了一些AllJoyn主要的概念.像总线,总线附件,总线对象,总线接口这种概念 ...

  2. android 跨进程通讯 AIDL

    跨进程如何通讯?两个进程无法直接通讯,通过Android系统底层间接通讯.基于service的aidl实现跨进程通讯. 什么叫AIDL? Android interface definition la ...

  3. android 史上最简单易懂的跨进程通讯(Messenger)!

    不需要AIDL也不需要复杂的ContentProvider,也不需要SharedPreferences或者共享存储文件! 只需要简单易懂的Messenger,它也称为信使,通过它可以在不同进程中传递m ...

  4. Android为TV端助力 史上最简单易懂的跨进程通讯(Messenger)!

    不需要AIDL也不需要复杂的ContentProvider,也不需要SharedPreferences或者共享存储文件! 只需要简单易懂的Messenger,它也称为信使,通过它可以在不同进程中传递m ...

  5. AppCompat v21 — Android 5.0之前版本设备的Material Design实现

    博客原文地址:http://android-developers.blogspot.com/2014/10/appcompat-v21-material-design-for-pre.html,要想打 ...

  6. [置顶] Xamarin android中使用signalr实现即时通讯

    前面几天也写了一些signalr的例子,不过都是在Web端,今天我就来实践一下如何在xamarin android中使用signalr,刚好工作中也用到了这个,也算是总结一下学到的东西吧,希望能帮助你 ...

  7. vue app混合开发蓝牙串口连接(报错java.io.IOException: read failed, socket might closed or timeout, read ret: -1;at android.bluetooth.BluetoothSocket.connect at js/BluetoothTool.js:329)

    我使用的uni-app <template> <view class="bluetooth"> <!-- 发送数据 --> <view c ...

  8. 以面向对象的思维,搭建Android与多ble蓝牙设备并发通讯小框架

    Android连接多蓝牙设备.蓝牙与多设备连接.蓝牙ble多设备并发操作.Android连接不了.Android ble开发框架.Android 连接蓝牙总结 前言 小白请绕道百度,本文适合有一定An ...

  9. 搭建Android与多ble蓝牙设备并发通讯小框架

    此框架支持多种不同类型的ble设备,同时连接.收发数据,互不干扰.比如APP同时连两个LED蓝牙灯.两个手环.一个蓝牙加热器,当然连接单个ble设备,或者只连接一种ble设备同样适用本框架. 前言 小 ...

  10. HTML5笔记:跨域通讯、多线程、本地存储和多图片上传技术

    最近做项目在前端我使用了很多新技术,这些技术有bootstrap.angularjs,不过最让我兴奋的还是使用了HTML5的技术,今天我想总结一些HTML5的技术,好记性不如烂笔头,写写文章可以很好的 ...

随机推荐

  1. [转帖]从小白到精通:揭秘perf工具的全部功能与操作技巧

    https://zhuanlan.zhihu.com/p/664396453 ​ 目录 收起 一.引言 二.理解perf工具的基本概念 三.安装与配置perf工具 3.1.不同操作系统的perf工具安 ...

  2. SQLServer备份恢复的总结-同名恢复与异名恢复

    SQLServer备份恢复的总结 前言 GUI 搞一把. 命令行太多了也没人看 自己还能省点心 备份 备份数据库建议一定要选择: 备份选项中的 压缩->压缩备份 历史经验一个7.6G的数据库能够 ...

  3. [转帖]SQL中 join 、in 、exists 使用场景和执行效率

    https://www.jianshu.com/p/c825c9bf42c2 众所周知,在sql 中,join /in /exists 都可以用来实现,"查询A表中在(或者不在)B表中的记录 ...

  4. [转帖]《Linux性能优化实战》笔记(21)—— 网络性能优化思路

    一. 确定优化目标 优化前,我会先问问自己,网络性能优化的目标是什么?实际上,虽然网络性能优化的整体目标,是降低网络延迟(如 RTT)和提高吞吐量(如BPS 和 PPS),但具体到不同应用中,每个指标 ...

  5. [转帖]鲲鹏性能优化十板斧——鲲鹏处理器NUMA简介与性能调优五步法

    https://www.cnblogs.com/huaweicloud/p/12166354.html 1.1 鲲鹏处理器NUMA简介 随着现代社会信息化.智能化的飞速发展,越来越多的设备接入互联网. ...

  6. [转帖]《Linux性能优化实战》笔记(二)—— CPU 上下文切换(上)

    上一篇的最后一个例子,在多个进程竞争CPU时,我们看到每个进程实际上%usr部分只有20%多,70%多是在wait,但是load远远高于单个进程使用CPU达到100%. 这让我想到之前看的RWP公开课 ...

  7. [转帖]Ceph优化系列(四):RocksDB 使用 ARM 64 位 CRC32C 硬件优化指令

    一.前言 CRC32(A cyclic redundancy check 32)应用于校验,为了保证数据的正确性,采用的一种检错手段. CRC32C (CRC32 Castagnoli)  与 CRC ...

  8. [转帖]【JVM】堆内存与栈内存详解

    堆和栈的定义 java把内存分成栈内存和堆内存. (1)栈内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配. 当在一段代码块中定义一个变量时,java就在栈中为这个变量分 ...

  9. 工单 工序外协 更改PR/PO

    工序外协详解介绍'https://blog.csdn.net/weixin_43814706/article/details/113586961' 需求:创建工序委外的工单时更改对应PR/PO 行文本 ...

  10. Nginx被它打败了?

    Nginx被它打败了? 我们经常使用Nginx作为我们系统的代理,通常情况下是完全够用的,但是有时候业务的复杂性,我们也需要使用在网关中去代理中做一些业务,这个时候Nginx也可以使用lua脚本扩展, ...