我们的目标是实现类似于桥接模式的那种局域网虚拟机主机互通并且能够访问外网的网络模式,以满足我们日常架设本地服务器测试环境的需求。但是又不想使用桥接模式,因为会占用真实局域网的 IP 地址,这点对于管理严格一点的公司内网来说非常棘手;切换网络容易产生 IP 冲突,就要针对虚拟机更改 IP 配置,非常的麻烦。
那哪种模式才能满足我们的需求呢?
以上介绍的单纯任何一种模式都无法满足,就算能满足也要做相应的设置,而不是默认配置完就能支持。比如 Host-only 模式就可以通过配置宿主机物理网卡和虚拟的网卡之间进行网络共享实现。但是考虑到不通 *** 作系统(例如:Mac OS X、Windows)设置的方式肯定存在差异,没法做到跨平台,换一个 *** 作系统部署同一套环境免不了学习成本,所以这种方式不予考虑。
那还有没有其他方式呢?
答案是有的,不过需要结合几种网络模式来实现。
这里我们采用 双网卡+Host-only+NAT 网络模式来实现。
虚拟机管理软件是支持定制硬件的(当然这里所说的硬件是指软件模拟的),所以添加网卡就可以满足。
假设你已经拥有了一台安装好 CentOS 7x 的虚拟机
Virtual Box 侧边栏选中你要配置的虚拟机,我这里是 centos7-origin ,点击右边的设置
选中侧边栏的网络一栏,点击”网卡1“标签页,配置连接方式为“仅主机网络”,界面名称选默认的就好
点击“网卡2”标签页,配置连接方式为“网络地址转换”,注意要勾上“启用网络连接”的选框。如果有需要,你也还可以配置“网卡3”、“网卡4”。这里我们只需要配置两张网卡
按以上步骤添加好网卡启动虚拟机
输入 ip addr 命令,此时能看到两张网卡,依次为前面我们设置的 Host-only 、 NAT 模式
cd /etc/sysconfig/network-scripts && ls 可以看到存在 ifcfg-enp0s3 这个网卡的配置文件,后缀对应的就是前面看到的网卡名
cp ifcfg-enp0s3 ifcfg-enp0s8 拷贝 ifcfg-enp0s3 命名 ifcfg-enp0s8 (对应前面的第二张网卡名)
nmcli con show (使用这个命令需要 NetworkManager 这个服务是开启的)查看网卡的 UUID 并通过 nmcli con show > ~/uuidtxt 记录到文件以备修改网卡配置用(这里文件名和路径自己定,也可以同我一样放在家目录,因为我没有用 ssh 工具连接虚拟机,到时候给网卡设置上对应的 UUID 没法复制粘贴,输入会比较麻烦,所以先把查看到的 UUID 信息输出到文件,修改网卡配置文件时可以读入文件的内容方便编辑)
我们采用静态 IP 的方式配置Host-only模式的网卡,也就是 enp0s3 这块
回到Virtual Box主界面点击菜单管理->主机网络管理器,d出对话框如下
这里采用固定 IP 配置,网络选项卡->手动配置如上
配置虚拟机 Host-only 模式的网卡 vi ifcfg-enp0s3
注意,网段需要跟上面主机网络配置的网卡处于同一网段,网关地址这里设置为主机网络配置的网卡地址一致
接着编辑 enp0s8 这张网卡, vi ifcfg-enp0s8 命令模式下光标移动到最后一行读入我们之前保存的网卡 UUID 文件 : r ~/uuidtxt 方便修改。因为这里是NAT模式,所以只要修改以上四个地方。
systemctl restart network 重启网络
ip addr 查看网卡是否配置成功,如上说明配置没问题
依次测试 Host-only 模式访问宿主机、 NAT 模式访问宿主机、访问外网
测试宿主机访问虚拟机
这样,整个网络便搭建好了,接着就可以欢乐的搭建本地服务器测试环境了作为主键,UUID长度过长,主键索引KeyLength长度过大,而影响能够基于内存的索引记录数量,进而影响基于内存的索引命中率,而基于硬盘进行索引查询性能很差。严重影响数据库服务器整体的性能表现。 建议,
如果考虑分布式,可以仿造MongoDB建立索引,能有效实现服务器同步,KeyLength也很小。如果使用UUID进行数据同步管理,需要对UUID字符串进行Djb的Hash算法,然后对Int/Long类型的哈希数值进行索引。第一次检索,通过UUIDHashCode将结果集范围缩小,再使用UUID定位具体数据。这样性能能高很多。使用Int类型的ID作为主键。UUID不作为主键,而仅作为数据同步的标记字段被使用。
随着wx的普及对开发同学来说一些业务场景会使用到“扫码登录”功能,特别是PC网页端,在此之前没有这方面的开发经历,所以接到这个需求的时候还是有点慌的,最终通过查阅网上的资料以及老大的指导下实现了这个功能,目前已经投入使用,实现之后还是蛮兴奋的。特此记录一下实现的过程。
扫码登陆的实现需要手机端的服务器和Web端的服务器配合实现。大致分为以下几步:
step1:网页端请求登陆二维码
要实现网页版的扫码登陆,用户必须先要请求一个登陆的二维码。Web端的服务器收到用户申请登陆二维码的请求后,会随机生成一个uuid(这个uuid作为页面的唯一标识符),并且会将这个uuid当做一个键值对的key存入后台Redis。存入Redis的这个键值对的value是什么我们待会再说。
需要注意的是存入Redis的键值对必须设置一个过期时间,不然的话拿着这个uuid登陆一次后就一直处于登陆状态了。
当浏览器端拿到Web服务端返回的二维码信息后,解析其中的uuid,并拿这个uuid不断去后台轮询是否已经登陆成功。如果后台已经登陆成功,Web端就自动跳转到登陆成功页面。不然的话会一直轮询,直到二维码失效(这里我们发现给二维码设置有效时间真的很有必要,如果二维码没有有效时间的话,会不断的轮询后台,给后台造成很大的压力)。
那么上面的关键点是Web端服务器是怎么判断用户是否已经扫码登陆成功过的呢? 请看下面的步骤。
step2:手机端将用户id存入Redis
用户请求到二维码后,就开始拿出手机,打开相应的App扫描二维码。扫描过程中手机会将uuid和手机端登陆后获得的token信息一起提交到手机端服务器。
手机端服务器会先拿token信息判断这个用户是否合法,是否已经正常登陆。如果判断已经正常登陆,那么会将这个用户的userId和提交过来的uuid当做一个键值对(uudi-userId)存入Redis。这边回答了步骤一种留下的问题。
简单来讲手机端做的工作就这么多。让我们继续回到Web端。
step3:web端轮询成功
步骤一中讲到:二维码登陆页会不停的轮询是否登陆成功。这边的依据就是Redis中存在uuid-userId键值对。如果这个键值对已经存在,说明手机端已经扫码登陆过。
Web端服务器一旦判断到手机端已经扫码登陆过,就可以拿着userId进行登陆。并将必要的用户信息和token信息返回Web前端。至此Web端登陆成功。
本文记录了一个扫码登陆的简单版本,但是也能描述扫码登陆的大致原理。实际开发过程中应该还是有许多细节需要考虑。比如安全问题等。具体的还是需要我们进行实战了。
欢迎大家一起讨论~
首先,要 *** 作蓝牙,先要在AndroidManifestxml里加入权限<uses-permissionandroid:name="androidpermissionBLUETOOTH_ADMIN" />
<uses-permissionandroid:name="androidpermissionBLUETOOTH" />
然后,看下api,Android所有关于蓝牙开发的类都在androidbluetooth包下。 而需要用到了就只有几个而已:
1BluetoothAdapter 顾名思义,蓝牙适配器,直到我们建立bluetoothSocket连接之前,都要不断 *** 作它BluetoothAdapter里的方法很多,常用的有以下几个:cancelDiscovery() 根据字面意思,是取消发现,也就是说正在搜索设备的时候调用这个方法将不再继续搜索disable()关闭蓝牙enable()打开蓝牙,这个方法打开蓝牙不会d出提示,更多的时候需要问下用户是否打开,一下这两行代码同样是打开蓝牙,不过会提示用户:Intemtenabler=new Intent(BluetoothAdapterACTION_REQUEST_ENABLE);
startActivityForResult(enabler,reCode);//同startActivity(enabler);
getAddress()获取本地蓝牙地址getDefaultAdapter()获取默认BluetoothAdapter,实际上,也只有这一种方法获取BluetoothAdaptergetName()获取本地蓝牙名称getRemoteDevice(String address)根据蓝牙地址获取远程蓝牙设备getState()获取本地蓝牙适配器当前状态(感觉可能调试的时候更需要)isDiscovering()判断当前是否正在查找设备,是返回trueisEnabled()判断蓝牙是否打开,已打开返回true,否则,返回falselistenUsingRfcommWithServiceRecord(String name,UUID uuid)根据名称,UUID创建并返回BluetoothServerSocket,这是创建BluetoothSocket服务器端的第一步startDiscovery()开始搜索,这是搜索的第一步。 2BluetoothDevice看名字就知道,这个类描述了一个蓝牙设备createRfcommSocketToServiceRecord(UUIDuuid)根据UUID创建并返回一个BluetoothSocket这个方法也是我们获取BluetoothDevice的目的——创建BluetoothSocket
这个类其他的方法,如getAddress(),getName(),同BluetoothAdapter;
3BluetoothServerSocket如果去除了Bluetooth相信大家一定再熟悉不过了,既然是Socket,方法就应该都差不多,这个类一种只有三个方法
两个重载的accept(),accept(inttimeout)两者的区别在于后面的方法指定了过时时间,需要注意的是,执行这两个方法的时候,直到接收到了客户端的请求(或是过期之后),都会阻塞线程,应该放在新线程里运行。
还有一点需要注意的是,这两个方法都返回一个BluetoothSocket,最后的连接也是服务器端与客户端的两个BluetoothSocket的连接。
4BluetoothSocket,跟BluetoothServerSocket相对,是客户端一共5个方法,不出意外,都会用到close(),关闭connect()连接getInptuStream()获取输入流getOutputStream()获取输出流getRemoteDevice()获取远程设备,这里指的是获取bluetoothSocket指定连接的那个远程蓝牙设备 。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)