Mina - 模拟同步请求
这篇博客主要就铺代码吧,Mina的一些基础知识可以参考:
http://www.cnblogs.com/huangfox/p/3458272.html
场景假设:
1.客户端发送用户信息,服务端根据用户名查询用户年龄。(模拟查询)
2.同步请求
3.协议:直接采用字段类型编码解码。
具体代码结构:

codec负责编码解码,TCPAcceptor服务端,TCPConnector客户端,User业务对象。
User
package com.fox.mina.base.c2; /**
* @author huangfox
* @date 2013年12月3日 上午11:23:55
*
*/
public class User {
String name;
int age; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} @Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
} }
编码、解码工厂
DefaultMinaCodecFactory
package com.fox.mina.base.c2.codec; import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder; /**
* @author huangfox
* @date 2013年12月5日 下午7:48:47
*
*/
public class DefaultMinaCodecFactory implements ProtocolCodecFactory {
ProtocolEncoder encoder;
ProtocolDecoder decoder; public DefaultMinaCodecFactory() { } public DefaultMinaCodecFactory(ProtocolEncoder encoder,
ProtocolDecoder decoder) {
super();
this.encoder = encoder;
this.decoder = decoder;
} @Override
public ProtocolEncoder getEncoder(IoSession session) throws Exception {
// TODO Auto-generated method stub
return encoder;
} @Override
public ProtocolDecoder getDecoder(IoSession session) throws Exception {
// TODO Auto-generated method stub
return decoder;
} public ProtocolEncoder getEncoder() {
return encoder;
} public void setEncoder(ProtocolEncoder encoder) {
this.encoder = encoder;
} public ProtocolDecoder getDecoder() {
return decoder;
} public void setDecoder(ProtocolDecoder decoder) {
this.decoder = decoder;
} }
编码器
FEncode
package com.fox.mina.base.c2.codec; import org.apache.commons.lang.ArrayUtils;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput; import com.fox.mina.base.c2.User; /**
* @author huangfox
* @date 2013年12月5日 下午7:49:21
*
*/
public class FEncoder extends ProtocolEncoderAdapter {
public static final NumberCodec numberCodec = DefaultNumberCodecs
.getBigEndianNumberCodec(); @Override
public void encode(IoSession session, Object message,
ProtocolEncoderOutput out) throws Exception {
byte[] bytes = null;
if (message instanceof User) {
User user = (User) message;
byte[] name = user.getName().getBytes();
bytes = ArrayUtils.addAll(bytes,
numberCodec.int2Bytes(name.length, 4));
bytes = ArrayUtils.addAll(bytes, name);
bytes = ArrayUtils.addAll(bytes,
numberCodec.int2Bytes(user.getAge(), 4));
out.write(IoBuffer.wrap(bytes));
} else {
System.out.println("encoder error!");
} } }
编码的协议:
用户姓名的长度(int 4字节)
用户年龄(int 4字节)
用户姓名(byte[])
解码器
FDecode
package com.fox.mina.base.c2.codec; import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput; import com.fox.mina.base.c2.User; /**
* @author huangfox
* @date 2013年12月3日 上午11:35:46
*
*/
public class FDecoder extends CumulativeProtocolDecoder {
public static final NumberCodec numberCodec = DefaultNumberCodecs
.getBigEndianNumberCodec(); @Override
protected boolean doDecode(IoSession session, IoBuffer in,
ProtocolDecoderOutput out) throws Exception {
int len = 0;
Object lenAttr = session.getAttribute("len");
if (lenAttr == null) {
if (in.remaining() < 4) {
return false;
}
byte[] buffer = new byte[4];
in.get(buffer);
len = numberCodec.bytes2Int(buffer, 4);
session.setAttribute("len", len);
} else {
len = (Integer) lenAttr;
}
//
String name = "";
Object nameAttr = session.getAttribute("name");
if (nameAttr == null) {
if (in.remaining() < len) {
return false;
}
byte[] buffer = new byte[len];
in.get(buffer);
name = new String(buffer);
session.setAttribute("name", name);
} else {
name = (String) nameAttr;
}
if (in.remaining() < 4) {
return false;
}
byte[] buffer = new byte[4];
in.get(buffer);
int age = numberCodec.bytes2Int(buffer, 4);
User u = new User();
u.setName(name);
u.setAge(age);
//
out.write(u);
//
session.removeAttribute("len");
session.removeAttribute("name"); return true;
} }
编码、解码使用的工具类:
package com.fox.mina.base.c2.codec;
public interface NumberCodec {
String convertCharset(String charset);
byte[] short2Bytes(short value, int byteLength);
byte[] int2Bytes(int value, int byteLength);
byte[] long2Bytes(long value, int byteLength);
byte[] float2Bytes(float value, int byteLength);
byte[] double2Bytes(double value, int byteLength);
short bytes2Short(byte[] bytes, int byteLength);
int bytes2Int(byte[] bytes, int byteLength);
long bytes2Long(byte[] bytes, int byteLength);
float bytes2Float(byte[] bytes, int byteLength);
double bytes2Double(byte[] bytes, int byteLength);
}
package com.fox.mina.base.c2.codec;
public class DefaultNumberCodecs {
private static int b2ui(byte b) {
return (int) (b + 256) % 256;
}
private static long b2ul(byte b) {
return (long) (b + 256) % 256;
}
private static NumberCodec littleEndianCodec = new NumberCodec() {
public int bytes2Int(byte[] bytes, int byteLength) {
int value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ui(bytes[i]) << (i * 8);
}
return value;
}
public long bytes2Long(byte[] bytes, int byteLength) {
long value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ul(bytes[i]) << (i * 8);
}
return value;
}
public short bytes2Short(byte[] bytes, int byteLength) {
short value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ui(bytes[i]) << (i * 8);
}
return value;
}
@Override
public float bytes2Float(byte[] bytes, int byteLength) {
int value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ui(bytes[i]) << (i * 8);
}
return Float.intBitsToFloat(value);
}
@Override
public double bytes2Double(byte[] bytes, int byteLength) {
long value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ul(bytes[i]) << (i * 8);
}
return Double.longBitsToDouble(value);
}
public byte[] int2Bytes(int value, int byteLength) {
byte[] bytes = new byte[byteLength];
for (int i = 0; i < byteLength; i++) {
int shiftCount = i * 8;
bytes[i] = (byte) ((value & (0x000000ff << shiftCount)) >> shiftCount);
}
return bytes;
}
public byte[] long2Bytes(long value, int byteLength) {
byte[] bytes = new byte[byteLength];
for (int i = 0; i < byteLength; i++) {
int shiftCount = i * 8;
bytes[i] = (byte) ((value & (0x00000000000000ffL << shiftCount)) >> shiftCount);
}
return bytes;
}
public byte[] short2Bytes(short value, int byteLength) {
byte[] bytes = new byte[byteLength];
for (int i = 0; i < byteLength; i++) {
int shiftCount = i * 8;
bytes[i] = (byte) ((value & (0x00ff << shiftCount)) >> shiftCount);
}
return bytes;
}
@Override
public byte[] float2Bytes(float value, int byteLength) {
byte[] bytes = new byte[byteLength];
// parse the bits that represent the floating-point number
// floatToRawIntBits gives the raw float bits without normalization
// using floatToRawIntBits is over 5 times as fast as
// floatToIntBits.
int x = Float.floatToRawIntBits(value);
for (int i = 0; i < byteLength; i++) {
int shiftCount = i * 8;
bytes[i] = (byte) ((x & (0x000000ff << shiftCount)) >> shiftCount);
}
return bytes;
}
@Override
public byte[] double2Bytes(double value, int byteLength) {
byte[] bytes = new byte[byteLength];
// parse the the bits that represent the floating-point number
long x = Double.doubleToRawLongBits(value);
for (int i = 0; i < byteLength; i++) {
int shiftCount = i * 8;
bytes[i] = (byte) ((x & (0x00000000000000ffL << shiftCount)) >> shiftCount);
}
return bytes;
}
public String convertCharset(String charset) {
if (charset.equals("UTF-16")) {
return "UTF-16LE";
} else {
return charset;
}
}
};
private static NumberCodec bigEndianCodec = new NumberCodec() {
public int bytes2Int(byte[] bytes, int byteLength) {
int value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ui(bytes[i]) << ((byteLength - 1 - i) * 8);
}
return value;
}
public long bytes2Long(byte[] bytes, int byteLength) {
long value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ul(bytes[i]) << ((byteLength - 1 - i) * 8);
}
return value;
}
public short bytes2Short(byte[] bytes, int byteLength) {
short value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ui(bytes[i]) << ((byteLength - 1 - i) * 8);
}
return value;
}
@Override
public float bytes2Float(byte[] bytes, int byteLength) {
int value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ui(bytes[i]) << ((byteLength - 1 - i) * 8);
}
return Float.intBitsToFloat(value);
}
@Override
public double bytes2Double(byte[] bytes, int byteLength) {
long value = 0;
for (int i = 0; i < byteLength; i++) {
value |= b2ul(bytes[i]) << ((byteLength - 1 - i) * 8);
}
return Double.longBitsToDouble(value);
}
public byte[] int2Bytes(int value, int byteLength) {
byte[] bytes = new byte[byteLength];
for (int i = 0; i < byteLength; i++) {
int shiftCount = ((byteLength - 1 - i) * 8);
bytes[i] = (byte) ((value & (0x000000ff << shiftCount)) >> shiftCount);
}
return bytes;
}
public byte[] long2Bytes(long value, int byteLength) {
byte[] bytes = new byte[byteLength];
for (int i = 0; i < byteLength; i++) {
int shiftCount = ((byteLength - 1 - i) * 8);
bytes[i] = (byte) ((value & (0x00000000000000ffL << shiftCount)) >> shiftCount);
}
return bytes;
}
public byte[] short2Bytes(short value, int byteLength) {
byte[] bytes = new byte[byteLength];
for (int i = 0; i < byteLength; i++) {
int shiftCount = ((byteLength - 1 - i) * 8);
bytes[i] = (byte) ((value & (0x00ff << shiftCount)) >> shiftCount);
}
return bytes;
}
@Override
public byte[] float2Bytes(float value, int byteLength) {
byte[] bytes = new byte[byteLength];
// parse the bits that represent the floating-point number
// floatToRawIntBits gives the raw float bits without normalization
// using floatToRawIntBits is over 5 times as fast as
// floatToIntBits.
int x = Float.floatToRawIntBits(value);
for (int i = 0; i < byteLength; i++) {
int shiftCount = ((byteLength - 1 - i) * 8);
bytes[i] = (byte) ((x & (0x000000ffL << shiftCount)) >> shiftCount);
}
return bytes;
}
@Override
public byte[] double2Bytes(double value, int byteLength) {
byte[] bytes = new byte[byteLength];
// parse the the bits that represent the floating-point number
long x = Double.doubleToRawLongBits(value);
for (int i = 0; i < byteLength; i++) {
int shiftCount = ((byteLength - 1 - i) * 8);
bytes[i] = (byte) ((x & (0x00000000000000ffL << shiftCount)) >> shiftCount);
}
return bytes;
}
public String convertCharset(String charset) {
if (charset.equals("UTF-16")) {
return "UTF-16BE";
} else {
return charset;
}
}
};
public static NumberCodec getBigEndianNumberCodec() {
return bigEndianCodec;
}
public static NumberCodec getLittleEndianNumberCodec() {
return littleEndianCodec;
}
}
服务端
TCPAcceptor
package com.fox.mina.base.c2; import java.io.IOException;
import java.net.InetSocketAddress; import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.core.session.IoSessionConfig;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import com.fox.mina.base.c2.codec.DefaultMinaCodecFactory;
import com.fox.mina.base.c2.codec.FDecoder;
import com.fox.mina.base.c2.codec.FEncoder; /**
* @author huangfox
* @date 2013年12月3日 上午11:15:53
*
*/
public class TCPAcceptor {
IoAcceptor acceptor = null;
String addr = "127.0.0.1";
int port = 9999; public TCPAcceptor() { } public void start() {
acceptor = new NioSocketAcceptor();
//
IoSessionConfig sessionConf = acceptor.getSessionConfig();
sessionConf.setReadBufferSize(2048);
// filter chain(codec)
acceptor.getFilterChain().addLast(
"codec",
new ProtocolCodecFilter(new DefaultMinaCodecFactory(
new FEncoder(), new FDecoder())));
// handler
acceptor.setHandler(new IOHandler());
//
try {// 可做重连
acceptor.bind(new InetSocketAddress(addr, port));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("server stated ... ");
} private class IOHandler extends IoHandlerAdapter { @Override
public void messageReceived(IoSession session, Object message)
throws Exception {
User u = (User) message;
System.out.println("[server]" + u.toString());
//模拟业务处理
u.setAge(u.hashCode()%100);
// send msg to client
session.write(u);
} } public static void main(String[] args) {
TCPAcceptor server = new TCPAcceptor();
server.start();
} }
客户端
TCPConnector
package com.fox.mina.base.c2; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.util.Random; import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.ReadFuture;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector; import com.fox.mina.base.c2.codec.DefaultMinaCodecFactory;
import com.fox.mina.base.c2.codec.FDecoder;
import com.fox.mina.base.c2.codec.FEncoder; /**
* @author huangfox
* @date 2013年12月3日 上午11:15:46
*
*/
public class TCPConnector {
IoConnector connector = null;
IoSession session = null;
String ip = "127.0.0.1";
int port = 9999; public TCPConnector() {
connector = new NioSocketConnector();
connector.getSessionConfig().setUseReadOperation(true);
connector.getFilterChain().addLast(
"codec",
new ProtocolCodecFilter(new DefaultMinaCodecFactory(
new FEncoder(), new FDecoder())));
connector.setHandler(new IOHander());
ConnectFuture connectF = connector.connect(new InetSocketAddress(ip,
port));
connectF.awaitUninterruptibly();
session = connectF.getSession();
} Random r = new Random(); public void sendMsg(User u) {
WriteFuture writeF = session.write(u);
writeF.awaitUninterruptibly();
if (writeF.getException() != null) {
System.out.println(writeF.getException().getMessage());
} else if (writeF.isWritten()) {
System.out.println("msg was sent!");
// 发送、接受
ReadFuture readF = session.read();
readF.awaitUninterruptibly(1000);
if (readF.getException() != null) {
System.out.println(readF.getException().getMessage());
} else {
System.out.println("[client]"+readF.getMessage().toString());
}
} else {
System.out.println("error!");
}
} public void close() {
this.connector.dispose();
} private class IOHander extends IoHandlerAdapter { } public static void main(String[] args) {
TCPConnector client = new TCPConnector();
while (true) {
BufferedReader r = new BufferedReader(new InputStreamReader(
System.in));
try {
System.out.println("输入:");
String msg = r.readLine();
User u = new User();
u.setName(msg);
client.sendMsg(u);
} catch (IOException e) {
e.printStackTrace();
} }
} }
注意:以上代码在多线程环境下是有问题的!!!
(最大字体的提示了!)
在TcpConnector中,只有一个session,如果多线程同时对这个session进行读写操作将发生问题(B可能拿到A的响应结果)。
最简单的处理方式就是,加入一个连接池,在sendMsg方法中先获取一个连接,用完以后再归还到连接池。可以理解为“一个线程独占一个连接”。
代码如下:
package com.fox.mina.base.c2; import java.net.InetSocketAddress;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.ReadFuture;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector; import com.fox.mina.base.c2.codec.DefaultMinaCodecFactory;
import com.fox.mina.base.c2.codec.FDecoder;
import com.fox.mina.base.c2.codec.FEncoder; /**
* @author huangfox
* @date 2013年12月3日 上午11:15:46
*
*/
public class TCPConnector {
IoConnector connector = null;
// IoSession session = null;
String ip = "127.0.0.1";
int port = 9999;
int poolSize = 1;
LinkedBlockingQueue<IoSession> pool; public TCPConnector() {
connector = new NioSocketConnector(10);
connector.getSessionConfig().setUseReadOperation(true);
connector.getFilterChain().addLast(
"codec",
new ProtocolCodecFilter(new DefaultMinaCodecFactory(
new FEncoder(), new FDecoder())));
connector.setHandler(new IOHander());
// pool
pool = new LinkedBlockingQueue<IoSession>(poolSize);
for (int i = 0; i < poolSize; i++) {
ConnectFuture connectF = connector.connect(new InetSocketAddress(
ip, port));
connectF.awaitUninterruptibly();
IoSession session = connectF.getSession();
try {
pool.put(session);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} Random r = new Random(); public void sendMsg(User u) {
IoSession session = null;
try {
session = pool.take();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (session == null)
return;
try {
WriteFuture writeF = session.write(u);
writeF.awaitUninterruptibly();
if (writeF.getException() != null) {
System.out.println(writeF.getException().getMessage());
} else if (writeF.isWritten()) {
// System.out.println("msg was sent!");
// 发送、接受
ReadFuture readF = session.read();
readF.awaitUninterruptibly();
if (readF.getException() != null) {
System.out.println(readF.getException().getMessage());
} else {
Date d = new Date(System.currentTimeMillis());
// System.out.println(Thread.currentThread().getId() + "-"
// + d.getSeconds() + "-" + session.hashCode());
// System.out.println("[client]"
// + readF.getMessage().toString());
}
} else {
System.out.println("error!");
}
} finally {
try {
pool.put(session);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} public void close() {
this.connector.dispose();
} private class IOHander extends IoHandlerAdapter { } }
扩展:
1.加入连接池(见上文)
2.加入连接、读写超时
Mina - 模拟同步请求的更多相关文章
- axios 模拟同步请求
axios本身没有同步请求,但是我们很多情况下必须得需要同步请求.那么应该怎么做? 上网查了一些资料有人说用es6的 async + assert 我不知道有没有效果,因为我的功能中是没啥效果的. ...
- 网络处理2-异步POST请求和同步请求
一.异步POST请求 假如请求路径是http://192.168.1.102:8080/MJServer/login,请求参数有2个: username :母鸡 pwd :123 1.POST请求细节 ...
- JSON(五)——同步请求中使用JSON格式字符串进行交互(不太常见的用法)
在同步请求中使用JSON格式进行数据交互的场景并不多,同步请求是浏览器直接与服务器进行数据交互的大多是用jsp的标签jstl和el表达式对请求中的数据进行数据的渲染.我也是在一次开发中要从其它服务器提 ...
- C#模拟httpwebrequest请求_向服务器模拟cookie发送
使用C#代码模拟web请求,是一种常用的方法,以前没专门整理过,这里暂时贴上自己整理的完整代码,以后再做梳理: public class MyRequest { #region 辅助方法 public ...
- 使用httpClient模拟http请求
在很多场景下都需要用到java代码来发送http请求:如和短信后台接口的数据发送,发送数据到微信后台接口中: 这里以apache下的httpClient类来模拟http请求:以get和Post请求为例 ...
- js_html_input中autocomplete="off"在chrom中失效的解决办法 使用JS模拟锚点跳转 js如何获取url参数 C#模拟httpwebrequest请求_向服务器模拟cookie发送 实习期学到的技术(一) LinqPad的变量比较功能 ASP.NET EF 使用LinqPad 快速学习Linq
js_html_input中autocomplete="off"在chrom中失效的解决办法 分享网上的2种办法: 1-可以在不需要默认填写的input框中设置 autocompl ...
- c# 模拟并发请求 ,只能并发2个连接。
使用 HttpWebRequest 模拟并发请求的时候,发现不管怎么提高thread 的数量,都没用,服务器端用计数器看到的都是2个连接,见下图(关于计数器怎么开,百度) 然后搜了一下,发现需要在ap ...
- ASP模拟POST请求异步提交数据的方法
这篇文章主要介绍了ASP模拟POST请求异步提交数据的方法,本文使用MSXML2.SERVERXMLHTTP.3.0实现POST请求,需要的朋友可以参考下 有时需要获取远程网站的某些信息,而服务器又限 ...
- java模拟post请求发送json
java模拟post请求发送json,用两种方式实现,第一种是HttpURLConnection发送post请求,第二种是使用httpclient模拟post请求, 方法一: package main ...
随机推荐
- HDU - 5157 :Harry and magic string (回文树,求多少对不相交的回文串)
Sample Input aca aaaa Sample Output 3 15 题意: 多组输入,每次给定字符串S(|S|<1e5),求多少对不相交的回文串. 思路:可以用回文树求出以每个位置 ...
- linux最常用的20个命令
玩过Linux的人都会知道,Linux中的命令的确是非常多,但是玩过Linux的人也从来不会因为Linux的命令如此之多而烦恼,因为我们只需要掌握我们最常用的命令就可以了.当然你也可以在使用时去找一下 ...
- java sftp 报错 Permission denied (没有权限;拒绝访问)
解决办法: 1.检查账号密码是否错误 2.检查freeSSHD是否是以管理员身份运行的 3.检查sftp路劲有没有配置错误,java通过sftp将图片文件传输到指定文件夹,如果这个文件夹在配置的当前目 ...
- 你不能阻止DOM
浏览器数据库景观 对于外行来说,浏览器数据库的世界可能是一个令人困惑的世界.Lawnchair,PouchDB,LocalForage,Dexie,Lovefield,LokiJS,AlaSQL,Ma ...
- Blender简单动画:一个小球从一座山上滚下.
简单动画:一个小球从一座山上滚下.注:[key]方括号内是快捷键; {大括号}内是模式,页签名称或选项等. ==== 1. 建模: == 1.1 山[shift A] 建立平面plane,可以大 ...
- php基础-5
php的面相对象 <?php class Hello { public function say_hello() { echo "hello"; } } $say = ne ...
- Linux配置浮动IP
在高可用集群环境中,一般都需要使用浮动IP来实现web高可用(High Availability). 浮动IP的概念以及为什么需要浮动IP请参考:https://blog.csdn.net/readi ...
- centos7安装部署mysql5.7服务器
因为自带源没有最新版的mysql,所以我们需要自己下载rpm包,先下载下面的rpm包源 https://repo.mysql.com//mysql57-community-release-el7-11 ...
- Nginx配置基于ip的虚拟主机
我是在centos7虚拟机上进行实验的 该实验基于添加好ip的基础上,如何给网卡添加ip请查阅我的博客 先来看一下我的ip [root@localhost nginx]# ifconfig ens33 ...
- 数学 它的内容,方法和意义 第三卷 (A. D. 亚历山大洛夫 著)
第十五章 实变数函数论 1. 绪论 2. 集合论 3. 实数 4. 点集 5. 集合的测度 6. 勒贝格积分 第十六章 线性代数 1. 线性代数的对象和它的工具 2. 线性空间 3. 线性方程组 4. ...