Netty私有协议栈开发编解码失败的问题

1
2
3
4
5
6
//解码器参数:固定
public static final int maxFrameLength = 1024 * 1024;
public static final int lengthFieldOffset = 4;
public static final int lengthFieldLength = 4;
public static final int lengthAdjustment = -8; //这个参数很关键,使用marshall工具,调用底层decode时候会做偏移
public static final int initialBytesToStrip = 0;

阅读全文

4类防御XSS的有效方法

XSS的本质

XSS事件发生在网站前端,在相关的数据替换到前端页面中时,新旧数据结合,混淆了页面原本的语义,产生了新的语义。以下面这种情况为例:

阅读全文

关于同一条TCP链接数据包到达顺序的问题

同一个TCP连接,数据包是不一定先发先到,但是对于TCP有一点特殊,若我们接受的数据包是在应用层,并且应用层用的是TCP的传输协议的话,这个顺序是保证,这个顺序的保证是在传输层保证的,举个例子:

client发生数据A,B给server,使用的TCP传输,client发送毫无疑问是先发送A,然后发送B,但是有些搞网络的同学可能会有这个疑问,A跟B在物理层走的链路不一样,传输速度不一样,B是会比A先到达Server,这个是没有错的,但是这个数据包被接受是在网络层跟传输层,

阅读全文

Mysql插入中文时提示编码问题

Mysql插入中文时提示:ERROR 1366 (HY000): Incorrect string value: ‘\xE5\x8F\xB0\xE5\xBC\x8F…’

1
2
首先通过语句查看:
show create table tdb_goods_cates ;

阅读全文

Spring Boot添加 Mybatis-generator 插件

支持Druid连接池设置、多个mapper.xml目录配置, 解决自定义sql扩展在每次执行插件后被覆盖的问题

1-pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.25</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>

<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.4</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
<configuration>
<configurationFile>src/main/resources/mybatis-generator-config.xml</configurationFile>
<!--允许移动生成的文件-->
<verbose>true</verbose>
<!--允许覆盖生成的文件-->
<overwrite>true</overwrite>
</configuration>
<executions>
<execution>
<id>Generate MyBatis Artifacts</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.7</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>

阅读全文

vue+webpack项目调试方法

修改配置

-sourcemap

./config/index.js, devtool这个选项, 如果设置为 ‘#source-map’,则可以生成.map文件,在chrome浏览器中调试的时候可以显示源代码

阅读全文

Vue项目打包后打开空白解决办法

1、记得改一下config下面的index.js中bulid模块导出的路径。因为index.html里边的内容都是通过script标签引入的,而你的路径不对,打开肯定是空白的。先看一下默认的路径

1
2
3
4
5
6
7
8
module.exports = {
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: true,

阅读全文

CentOS下Tomcat服务器宕机自动启动方法

监控启动脚本monitor.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/bin/sh
# 获取tomcat进程ID /usr/local/tomcat
TomcatID=$(ps -ef |grep tomcat |grep -w 'tomcat'|grep -v 'grep'|awk '{print $2}')

# tomcat启动程序(这里注意tomcat实际安装的路径)
StartTomcat=/usr/local/tomcat/bin/startup.sh

# 定义要监控的页面地址
WebUrl=http://localhost:8080

# 日志输出
TomcatMonitorLog=/usr/local/tomcat/logs/TomcatMonitor.log

Monitor()
{
echo "[info]开始监控tomcat...[$(date +'%F %H:%M:%S')]"
if [[ $TomcatID ]];then # 这里判断TOMCAT进程是否存在
echo "[info]当前tomcat进程ID为:$TomcatID,继续检测页面..."
# 检测是否启动成功(成功的话页面会返回状态"200")
TomcatServiceCode=$(curl -I -m 10 -o /dev/null -s -w %{http_code} $WebUrl)
if [ $TomcatServiceCode -eq 200 ];then
echo "[info]页面返回码为$TomcatServiceCode,tomcat启动成功,测试页面正常......"
else
echo "[error]tomcat页面出错,请注意......状态码为$TomcatServiceCode,错误日志已输出到$GetPageInfo"
echo "[error]页面访问出错,开始重启tomcat"
kill -9 $TomcatID # 杀掉原tomcat进程
sleep 3
rm -rf $TomcatCache # 清理tomcat缓存
$StartTomcat
fi
else
echo "[error]tomcat进程不存在!tomcat开始自动重启..."
echo "[info]$StartTomcat,请稍候......"
#rm -rf $TomcatCache
$StartTomcat
fi
echo "------------------------------"
}
Monitor>>$TomcatMonitorLog

阅读全文

在intellij中打jar包,运行提示没有主清单属性

  • 在Intellij中通过Project Structure - Artifacts打jar包,每次java -jar运行时候总是提示没有主清单属性。查看Manifest.mf文件里面确实没有Main-Class.

可能是 IntelliJ 的问题

    阅读全文

    解决Ngrok Server无法认证AuthTokens问题

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    package server

    import (
    "fmt"
    "io"
    "ngrok/conn"
    "ngrok/msg"
    "ngrok/util"
    "ngrok/version"
    "runtime/debug"
    "strings"
    "time"
    "os"
    "bufio"
    "errors"
    "os/exec"
    "path/filepath"
    )

    const (
    pingTimeoutInterval = 30 * time.Second
    connReapInterval = 10 * time.Second
    controlWriteTimeout = 10 * time.Second
    proxyStaleDuration = 60 * time.Second
    proxyMaxPoolSize = 10
    )

    type Control struct {
    // auth message
    auth *msg.Auth

    // actual connection
    conn conn.Conn

    // put a message in this channel to send it over
    // conn to the client
    out chan (msg.Message)

    // read from this channel to get the next message sent
    // to us over conn by the client
    in chan (msg.Message)

    // the last time we received a ping from the client - for heartbeats
    lastPing time.Time

    // all of the tunnels this control connection handles
    tunnels []*Tunnel

    // proxy connections
    proxies chan conn.Conn

    // identifier
    id string

    // synchronizer for controlled shutdown of writer()
    writerShutdown *util.Shutdown

    // synchronizer for controlled shutdown of reader()
    readerShutdown *util.Shutdown

    // synchronizer for controlled shutdown of manager()
    managerShutdown *util.Shutdown

    // synchronizer for controller shutdown of entire Control
    shutdown *util.Shutdown
    }

    func GetCurrentPath() (string, error) {
    file, err := exec.LookPath(os.Args[0])
    if err != nil {
    return "", err
    }
    path, err := filepath.Abs(file)
    if err != nil {
    return "", err
    }
    i := strings.LastIndex(path, "/")
    if i < 0 {
    i = strings.LastIndex(path, "\\")
    }
    if i < 0 {
    return "", errors.New(`error: Can't find "/" or "\".`)
    }
    return string(path[0 : i+1]), nil
    }

    func NewControl(ctlConn conn.Conn, authMsg *msg.Auth) {
    var err error

    // create the object
    c := &Control{
    auth: authMsg,
    conn: ctlConn,
    out: make(chan msg.Message),
    in: make(chan msg.Message),
    proxies: make(chan conn.Conn, 10),
    lastPing: time.Now(),
    writerShutdown: util.NewShutdown(),
    readerShutdown: util.NewShutdown(),
    managerShutdown: util.NewShutdown(),
    shutdown: util.NewShutdown(),
    }

    failAuth := func(e error) {
    _ = msg.WriteMsg(ctlConn, &msg.AuthResp{Error: e.Error()})
    ctlConn.Close()
    }
    readLine := func(token string, filename string) (bool, error) {
    tokenpath, err := GetCurrentPath()
    if err != nil {
    fmt.Println("---------->current path faild")
    return false, nil;
    }
    if token == "" {
    fmt.Println("---------->token=" + token)
    return false, nil;
    }
    f, err := os.Open(tokenpath + filename)
    if err != nil {
    fmt.Println("---------->open token file fail=" + filename + ", path=" + tokenpath)
    fmt.Println(err)
    return false, err
    }
    buf := bufio.NewReader(f)
    for {
    line, err := buf.ReadString('\n')
    line = strings.TrimSpace(line)
    fmt.Println("---------->open token file line=" + line)
    if line == token {
    return true, nil
    }
    if err != nil {
    if err == io.EOF {
    fmt.Println("---------->read token file io.EOF")
    return false, nil
    }
    fmt.Println("---------->read token file err")
    return false, err
    }
    }
    fmt.Println("---------->read token and none equals")
    return false, nil
    }
    // register the clientid
    c.id = authMsg.ClientId
    if c.id == "" {
    // it's a new session, assign an ID
    if c.id, err = util.SecureRandId(16); err != nil {
    failAuth(err)
    return
    }
    }

    // set logging prefix
    ctlConn.SetType("ctl")
    ctlConn.AddLogPrefix(c.id)

    if authMsg.Version != version.Proto {
    failAuth(fmt.Errorf("Incompatible versions. Server %s, client %s. Download a new version at http://ngrok.com", version.MajorMinor(), authMsg.Version))
    return
    }
    authd, err := readLine(authMsg.User, "authtokens.txt")

    if authd != true {
    failAuth(fmt.Errorf("authtoken %s invalid", "is"));
    return
    }

    // register the control
    if replaced := controlRegistry.Add(c.id, c); replaced != nil {
    replaced.shutdown.WaitComplete()
    }

    // start the writer first so that the following messages get sent
    go c.writer()

    // Respond to authentication
    c.out <- &msg.AuthResp{
    Version: version.Proto,
    MmVersion: version.MajorMinor(),
    ClientId: c.id,
    }

    // As a performance optimization, ask for a proxy connection up front
    c.out <- &msg.ReqProxy{}

    // manage the connection
    go c.manager()
    go c.reader()
    go c.stopper()
    }

    // Register a new tunnel on this control connection
    func (c *Control) registerTunnel(rawTunnelReq *msg.ReqTunnel) {
    for _, proto := range strings.Split(rawTunnelReq.Protocol, "+") {
    tunnelReq := *rawTunnelReq
    tunnelReq.Protocol = proto

    c.conn.Debug("Registering new tunnel")
    t, err := NewTunnel(&tunnelReq, c)
    if err != nil {
    c.out <- &msg.NewTunnel{Error: err.Error()}
    if len(c.tunnels) == 0 {
    c.shutdown.Begin()
    }

    // we're done
    return
    }

    // add it to the list of tunnels
    c.tunnels = append(c.tunnels, t)

    // acknowledge success
    c.out <- &msg.NewTunnel{
    Url: t.url,
    Protocol: proto,
    ReqId: rawTunnelReq.ReqId,
    }

    rawTunnelReq.Hostname = strings.Replace(t.url, proto + "://", "", 1)
    }
    }

    func (c *Control) manager() {
    // don't crash on panics
    defer func() {
    if err := recover(); err != nil {
    c.conn.Info("Control::manager failed with error %v: %s", err, debug.Stack())
    }
    }()

    // kill everything if the control manager stops
    defer c.shutdown.Begin()

    // notify that manager() has shutdown
    defer c.managerShutdown.Complete()

    // reaping timer for detecting heartbeat failure
    reap := time.NewTicker(connReapInterval)
    defer reap.Stop()

    for {
    select {
    case <-reap.C:
    if time.Since(c.lastPing) > pingTimeoutInterval {
    c.conn.Info("Lost heartbeat")
    c.shutdown.Begin()
    }

    case mRaw, ok := <-c.in:
    // c.in closes to indicate shutdown
    if !ok {
    return
    }

    switch m := mRaw.(type) {
    case *msg.ReqTunnel:
    c.registerTunnel(m)

    case *msg.Ping:
    c.lastPing = time.Now()
    c.out <- &msg.Pong{}
    }
    }
    }
    }

    func (c *Control) writer() {
    defer func() {
    if err := recover(); err != nil {
    c.conn.Info("Control::writer failed with error %v: %s", err, debug.Stack())
    }
    }()

    // kill everything if the writer() stops
    defer c.shutdown.Begin()

    // notify that we've flushed all messages
    defer c.writerShutdown.Complete()

    // write messages to the control channel
    for m := range c.out {
    c.conn.SetWriteDeadline(time.Now().Add(controlWriteTimeout))
    if err := msg.WriteMsg(c.conn, m); err != nil {
    panic(err)
    }
    }
    }

    func (c *Control) reader() {
    defer func() {
    if err := recover(); err != nil {
    c.conn.Warn("Control::reader failed with error %v: %s", err, debug.Stack())
    }
    }()

    // kill everything if the reader stops
    defer c.shutdown.Begin()

    // notify that we're done
    defer c.readerShutdown.Complete()

    // read messages from the control channel
    for {
    if msg, err := msg.ReadMsg(c.conn); err != nil {
    if err == io.EOF {
    c.conn.Info("EOF")
    return
    } else {
    panic(err)
    }
    } else {
    // this can also panic during shutdown
    c.in <- msg
    }
    }
    }

    func (c *Control) stopper() {
    defer func() {
    if r := recover(); r != nil {
    c.conn.Error("Failed to shut down control: %v", r)
    }
    }()

    // wait until we're instructed to shutdown
    c.shutdown.WaitBegin()

    // remove ourself from the control registry
    controlRegistry.Del(c.id)

    // shutdown manager() so that we have no more work to do
    close(c.in)
    c.managerShutdown.WaitComplete()

    // shutdown writer()
    close(c.out)
    c.writerShutdown.WaitComplete()

    // close connection fully
    c.conn.Close()

    // shutdown all of the tunnels
    for _, t := range c.tunnels {
    t.Shutdown()
    }

    // shutdown all of the proxy connections
    close(c.proxies)
    for p := range c.proxies {
    p.Close()
    }

    c.shutdown.Complete()
    c.conn.Info("Shutdown complete")
    }

    func (c *Control) RegisterProxy(conn conn.Conn) {
    conn.AddLogPrefix(c.id)

    conn.SetDeadline(time.Now().Add(proxyStaleDuration))
    select {
    case c.proxies <- conn:
    conn.Info("Registered")
    default:
    conn.Info("Proxies buffer is full, discarding.")
    conn.Close()
    }
    }

    // Remove a proxy connection from the pool and return it
    // If not proxy connections are in the pool, request one
    // and wait until it is available
    // Returns an error if we couldn't get a proxy because it took too long
    // or the tunnel is closing
    func (c *Control) GetProxy() (proxyConn conn.Conn, err error) {
    var ok bool

    // get a proxy connection from the pool
    select {
    case proxyConn, ok = <-c.proxies:
    if !ok {
    err = fmt.Errorf("No proxy connections available, control is closing")
    return
    }
    default:
    // no proxy available in the pool, ask for one over the control channel
    c.conn.Debug("No proxy in pool, requesting proxy from control . . .")
    if err = util.PanicToError(func() {
    c.out <- &msg.ReqProxy{}
    }); err != nil {
    return
    }

    select {
    case proxyConn, ok = <-c.proxies:
    if !ok {
    err = fmt.Errorf("No proxy connections available, control is closing")
    return
    }

    case <-time.After(pingTimeoutInterval):
    err = fmt.Errorf("Timeout trying to get proxy connection")
    return
    }
    }
    return
    }

    // Called when this control is replaced by another control
    // this can happen if the network drops out and the client reconnects
    // before the old tunnel has lost its heartbeat
    func (c *Control) Replaced(replacement *Control) {
    c.conn.Info("Replaced by control: %s", replacement.conn.Id())

    // set the control id to empty string so that when stopper()
    // calls registry.Del it won't delete the replacement
    c.id = ""

    // tell the old one to shutdown
    c.shutdown.Begin()
    }

    阅读全文