Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
G
getty
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wei.xuan
getty
Commits
bfb3fc6a
Commit
bfb3fc6a
authored
Mar 15, 2018
by
AlexStocks
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add udp echo
parent
3a269e7a
Show whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
2373 additions
and
4 deletions
+2373
-4
change_log.md
echo/tcp-echo/change_log.md
+1
-1
server.go
echo/tcp-echo/server/app/server.go
+0
-1
change_log.md
echo/udp-echo/change_log.md
+17
-0
client.go
echo/udp-echo/client/app/client.go
+164
-0
config.go
echo/udp-echo/client/app/config.go
+155
-0
echo.go
echo/udp-echo/client/app/echo.go
+145
-0
handler.go
echo/udp-echo/client/app/handler.go
+83
-0
main.go
echo/udp-echo/client/app/main.go
+188
-0
readwriter.go
echo/udp-echo/client/app/readwriter.go
+76
-0
version.go
echo/udp-echo/client/app/version.go
+14
-0
load.sh
echo/udp-echo/client/assembly/bin/load.sh
+132
-0
app.properties
echo/udp-echo/client/assembly/common/app.properties
+17
-0
build.sh
echo/udp-echo/client/assembly/common/build.sh
+74
-0
test.sh
echo/udp-echo/client/assembly/linux/test.sh
+29
-0
test.sh
echo/udp-echo/client/assembly/mac/test.sh
+29
-0
test.sh
echo/udp-echo/client/assembly/windows/test.sh
+29
-0
config.toml
echo/udp-echo/client/profiles/test/config.toml
+46
-0
log.xml
echo/udp-echo/client/profiles/test/log.xml
+63
-0
config.go
echo/udp-echo/server/app/config.go
+132
-0
echo.go
echo/udp-echo/server/app/echo.go
+146
-0
handler.go
echo/udp-echo/server/app/handler.go
+167
-0
readwriter.go
echo/udp-echo/server/app/readwriter.go
+76
-0
server.go
echo/udp-echo/server/app/server.go
+172
-0
version.go
echo/udp-echo/server/app/version.go
+14
-0
load.sh
echo/udp-echo/server/assembly/bin/load.sh
+132
-0
app.properties
echo/udp-echo/server/assembly/common/app.properties
+16
-0
build.sh
echo/udp-echo/server/assembly/common/build.sh
+74
-0
test.sh
echo/udp-echo/server/assembly/linux/test.sh
+29
-0
test.sh
echo/udp-echo/server/assembly/mac/test.sh
+29
-0
test.sh
echo/udp-echo/server/assembly/windows/test.sh
+29
-0
config.toml
echo/udp-echo/server/profiles/test/config.toml
+30
-0
log.xml
echo/udp-echo/server/profiles/test/log.xml
+63
-0
change_log.md
echo/wss-echo/change_log.md
+2
-2
No files found.
echo/tcp-echo/change_log.md
View file @
bfb3fc6a
#
ws
-echo #
#
tcp
-echo #
---
---
*getty tcp examples of Echo Example*
*getty tcp examples of Echo Example*
...
...
echo/tcp-echo/server/app/server.go
View file @
bfb3fc6a
...
@@ -27,7 +27,6 @@ import (
...
@@ -27,7 +27,6 @@ import (
"github.com/AlexStocks/goext/log"
"github.com/AlexStocks/goext/log"
"github.com/AlexStocks/goext/net"
"github.com/AlexStocks/goext/net"
log
"github.com/AlexStocks/log4go"
log
"github.com/AlexStocks/log4go"
"github.com/pingcap/tidb/ast"
)
)
const
(
const
(
...
...
echo/udp-echo/change_log.md
0 → 100644
View file @
bfb3fc6a
# udp-echo #
---
*getty udp examples of Echo Example*
## LICENSE ##
---
> LICENCE : Apache License 2.0
## develop history ##
---
-
2018/03/14
> init
echo/udp-echo/client/app/client.go
0 → 100644
View file @
bfb3fc6a
/******************************************************
# DESC : echo client
# AUTHOR : Alex Stocks
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-09-06 17:24
# FILE : client.go
******************************************************/
package
main
import
(
"math/rand"
"sync"
"sync/atomic"
"time"
)
import
(
"github.com/AlexStocks/getty"
log
"github.com/AlexStocks/log4go"
)
var
(
reqID
uint32
src
=
rand
.
NewSource
(
time
.
Now
()
.
UnixNano
())
)
func
init
()
{
rand
.
Seed
(
time
.
Now
()
.
UnixNano
())
}
////////////////////////////////////////////////////////////////////
// echo client
////////////////////////////////////////////////////////////////////
type
EchoClient
struct
{
lock
sync
.
RWMutex
sessions
[]
*
clientEchoSession
gettyClient
*
getty
.
Client
}
func
(
this
*
EchoClient
)
isAvailable
()
bool
{
if
this
.
selectSession
()
==
nil
{
return
false
}
return
true
}
func
(
this
*
EchoClient
)
close
()
{
client
.
lock
.
Lock
()
if
client
.
gettyClient
!=
nil
{
for
_
,
s
:=
range
this
.
sessions
{
log
.
Info
(
"close client session{%s, last active:%s, request number:%d}"
,
s
.
session
.
Stat
(),
s
.
session
.
GetActive
()
.
String
(),
s
.
reqNum
)
s
.
session
.
Close
()
}
client
.
gettyClient
.
Close
()
client
.
gettyClient
=
nil
client
.
sessions
=
client
.
sessions
[
:
0
]
}
client
.
lock
.
Unlock
()
}
func
(
this
*
EchoClient
)
selectSession
()
getty
.
Session
{
// get route server session
this
.
lock
.
RLock
()
defer
this
.
lock
.
RUnlock
()
count
:=
len
(
this
.
sessions
)
if
count
==
0
{
log
.
Info
(
"client session array is nil..."
)
return
nil
}
return
this
.
sessions
[
rand
.
Int31n
(
int32
(
count
))]
.
session
}
func
(
this
*
EchoClient
)
addSession
(
session
getty
.
Session
)
{
log
.
Debug
(
"add session{%s}"
,
session
.
Stat
())
if
session
==
nil
{
return
}
this
.
lock
.
Lock
()
this
.
sessions
=
append
(
this
.
sessions
,
&
clientEchoSession
{
session
:
session
})
this
.
lock
.
Unlock
()
}
func
(
this
*
EchoClient
)
removeSession
(
session
getty
.
Session
)
{
if
session
==
nil
{
return
}
this
.
lock
.
Lock
()
for
i
,
s
:=
range
this
.
sessions
{
if
s
.
session
==
session
{
this
.
sessions
=
append
(
this
.
sessions
[
:
i
],
this
.
sessions
[
i
+
1
:
]
...
)
log
.
Debug
(
"delete session{%s}, its index{%d}"
,
session
.
Stat
(),
i
)
break
}
}
log
.
Info
(
"after remove session{%s}, left session number:%d"
,
session
.
Stat
(),
len
(
this
.
sessions
))
this
.
lock
.
Unlock
()
}
func
(
this
*
EchoClient
)
updateSession
(
session
getty
.
Session
)
{
if
session
==
nil
{
return
}
this
.
lock
.
Lock
()
for
i
,
s
:=
range
this
.
sessions
{
if
s
.
session
==
session
{
this
.
sessions
[
i
]
.
reqNum
++
break
}
}
this
.
lock
.
Unlock
()
}
func
(
this
*
EchoClient
)
getClientEchoSession
(
session
getty
.
Session
)
(
clientEchoSession
,
error
)
{
var
(
err
error
echoSession
clientEchoSession
)
this
.
lock
.
Lock
()
err
=
errSessionNotExist
for
_
,
s
:=
range
this
.
sessions
{
if
s
.
session
==
session
{
echoSession
=
*
s
err
=
nil
break
}
}
this
.
lock
.
Unlock
()
return
echoSession
,
err
}
func
(
this
*
EchoClient
)
heartbeat
(
session
getty
.
Session
)
{
var
pkg
EchoPackage
pkg
.
H
.
Magic
=
echoPkgMagic
pkg
.
H
.
LogID
=
(
uint32
)(
src
.
Int63
())
pkg
.
H
.
Sequence
=
atomic
.
AddUint32
(
&
reqID
,
1
)
// pkg.H.ServiceID = 0
pkg
.
H
.
Command
=
heartbeatCmd
pkg
.
B
=
echoHeartbeatRequestString
pkg
.
H
.
Len
=
(
uint16
)(
len
(
pkg
.
B
)
+
1
)
if
err
:=
session
.
WritePkg
(
&
pkg
,
WritePkgTimeout
);
err
!=
nil
{
log
.
Warn
(
"session.WritePkg(session{%s}, pkg{%s}) = error{%v}"
,
session
.
Stat
(),
pkg
,
err
)
session
.
Close
()
this
.
removeSession
(
session
)
}
}
echo/udp-echo/client/app/config.go
0 → 100644
View file @
bfb3fc6a
/******************************************************
# DESC : env var & configure
# MAINTAINER : Alex Stocks
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-09-06 16:53
# FILE : config.go
******************************************************/
package
main
import
(
"fmt"
"os"
"path"
"time"
)
import
(
log
"github.com/AlexStocks/log4go"
config
"github.com/koding/multiconfig"
)
const
(
APP_CONF_FILE
string
=
"APP_CONF_FILE"
APP_LOG_CONF_FILE
string
=
"APP_LOG_CONF_FILE"
)
var
(
conf
*
Config
)
type
(
GettySessionParam
struct
{
CompressEncoding
bool
`default:"false"`
UdpRBufSize
int
`default:"262144"`
UdpWBufSize
int
`default:"65536"`
PkgRQSize
int
`default:"1024"`
PkgWQSize
int
`default:"1024"`
UdpReadTimeout
string
`default:"1s"`
udpReadTimeout
time
.
Duration
UdpWriteTimeout
string
`default:"5s"`
udpWriteTimeout
time
.
Duration
WaitTimeout
string
`default:"7s"`
waitTimeout
time
.
Duration
SessionName
string
`default:"echo-client"`
}
// Config holds supported types by the multiconfig package
Config
struct
{
// local
AppName
string
`default:"echo-client"`
LocalHost
string
`default:"127.0.0.1"`
// server
ServerHost
string
`default:"127.0.0.1"`
ServerPort
int
`default:"10000"`
ProfilePort
int
`default:"10086"`
// session pool
ConnectionNum
int
`default:"16"`
ConnectInterval
string
`default:"5s"`
connectInterval
time
.
Duration
// heartbeat
HeartbeatPeriod
string
`default:"15s"`
heartbeatPeriod
time
.
Duration
// session
SessionTimeout
string
`default:"60s"`
sessionTimeout
time
.
Duration
// echo
EchoString
string
`default:"hello"`
EchoTimes
int
`default:"10"`
// app
FailFastTimeout
string
`default:"5s"`
failFastTimeout
time
.
Duration
// session tcp parameters
GettySessionParam
GettySessionParam
`required:"true"`
}
)
func
initConf
()
{
var
(
err
error
confFile
string
)
// configure
confFile
=
os
.
Getenv
(
APP_CONF_FILE
)
if
confFile
==
""
{
panic
(
fmt
.
Sprintf
(
"application configure file name is nil"
))
return
// I know it is of no usage. Just Err Protection.
}
if
path
.
Ext
(
confFile
)
!=
".toml"
{
panic
(
fmt
.
Sprintf
(
"application configure file name{%v} suffix must be .toml"
,
confFile
))
return
}
conf
=
new
(
Config
)
config
.
MustLoadWithPath
(
confFile
,
conf
)
conf
.
connectInterval
,
err
=
time
.
ParseDuration
(
conf
.
ConnectInterval
)
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"time.ParseDuration(ConnectionInterval{%#v}) = error{%v}"
,
conf
.
ConnectInterval
,
err
))
return
}
conf
.
heartbeatPeriod
,
err
=
time
.
ParseDuration
(
conf
.
HeartbeatPeriod
)
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"time.ParseDuration(HeartbeatPeroid{%#v}) = error{%v}"
,
conf
.
HeartbeatPeriod
,
err
))
return
}
conf
.
sessionTimeout
,
err
=
time
.
ParseDuration
(
conf
.
SessionTimeout
)
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"time.ParseDuration(SessionTimeout{%#v}) = error{%v}"
,
conf
.
SessionTimeout
,
err
))
return
}
conf
.
failFastTimeout
,
err
=
time
.
ParseDuration
(
conf
.
FailFastTimeout
)
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"time.ParseDuration(FailFastTimeout{%#v}) = error{%v}"
,
conf
.
FailFastTimeout
,
err
))
return
}
conf
.
GettySessionParam
.
udpReadTimeout
,
err
=
time
.
ParseDuration
(
conf
.
GettySessionParam
.
UdpReadTimeout
)
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"time.ParseDuration(UdpReadTimeout{%#v}) = error{%v}"
,
conf
.
GettySessionParam
.
UdpReadTimeout
,
err
))
return
}
conf
.
GettySessionParam
.
udpWriteTimeout
,
err
=
time
.
ParseDuration
(
conf
.
GettySessionParam
.
UdpWriteTimeout
)
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"time.ParseDuration(UdpWriteTimeout{%#v}) = error{%v}"
,
conf
.
GettySessionParam
.
UdpWriteTimeout
,
err
))
return
}
conf
.
GettySessionParam
.
waitTimeout
,
err
=
time
.
ParseDuration
(
conf
.
GettySessionParam
.
WaitTimeout
)
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"time.ParseDuration(WaitTimeout{%#v}) = error{%v}"
,
conf
.
GettySessionParam
.
WaitTimeout
,
err
))
return
}
// gxlog.Info("config{%#v}\n", conf)
// log
confFile
=
os
.
Getenv
(
APP_LOG_CONF_FILE
)
if
confFile
==
""
{
panic
(
fmt
.
Sprintf
(
"log configure file name is nil"
))
return
}
if
path
.
Ext
(
confFile
)
!=
".xml"
{
panic
(
fmt
.
Sprintf
(
"log configure file name{%v} suffix must be .xml"
,
confFile
))
return
}
log
.
LoadConfiguration
(
confFile
)
log
.
Info
(
"config{%#v}"
,
conf
)
return
}
echo/udp-echo/client/app/echo.go
0 → 100644
View file @
bfb3fc6a
/******************************************************
# DESC : echo package
# AUTHOR : Alex Stocks
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-08-22 17:44
# FILE : echo.go
******************************************************/
package
main
import
(
"bytes"
"encoding/binary"
"errors"
"fmt"
"unsafe"
)
import
(
log
"github.com/AlexStocks/log4go"
)
////////////////////////////////////////////
// echo command
////////////////////////////////////////////
type
echoCommand
uint32
const
(
heartbeatCmd
=
iota
echoCmd
)
var
echoCommandStrings
=
[
...
]
string
{
"heartbeat"
,
"echo"
,
}
func
(
c
echoCommand
)
String
()
string
{
return
echoCommandStrings
[
c
]
}
////////////////////////////////////////////
// EchoPkgHandler
////////////////////////////////////////////
const
(
echoPkgMagic
=
0x20160905
maxEchoStringLen
=
0xff
echoHeartbeatRequestString
=
"ping"
echoHeartbeatResponseString
=
"pong"
)
var
(
ErrNotEnoughStream
=
errors
.
New
(
"packet stream is not enough"
)
ErrTooLargePackage
=
errors
.
New
(
"package length is exceed the echo package's legal maximum length."
)
ErrIllegalMagic
=
errors
.
New
(
"package magic is not right."
)
)
var
(
echoPkgHeaderLen
int
)
func
init
()
{
echoPkgHeaderLen
=
(
int
)((
uint
)(
unsafe
.
Sizeof
(
EchoPkgHeader
{})))
}
type
EchoPkgHeader
struct
{
Magic
uint32
LogID
uint32
// log id
Sequence
uint32
// request/response sequence
ServiceID
uint32
// service id
Command
uint32
// operation command code
Code
int32
// error code
Len
uint16
// body length
_
uint16
_
int32
// reserved, maybe used as package md5 checksum
}
type
EchoPackage
struct
{
H
EchoPkgHeader
B
string
}
func
(
this
EchoPackage
)
String
()
string
{
return
fmt
.
Sprintf
(
"log id:%d, sequence:%d, command:%s, echo string:%s"
,
this
.
H
.
LogID
,
this
.
H
.
Sequence
,
(
echoCommand
(
this
.
H
.
Command
))
.
String
(),
this
.
B
)
}
func
(
this
EchoPackage
)
Marshal
()
(
*
bytes
.
Buffer
,
error
)
{
var
(
err
error
buf
*
bytes
.
Buffer
)
buf
=
&
bytes
.
Buffer
{}
err
=
binary
.
Write
(
buf
,
binary
.
LittleEndian
,
this
.
H
)
if
err
!=
nil
{
return
nil
,
err
}
buf
.
WriteByte
((
byte
)(
len
(
this
.
B
)))
buf
.
WriteString
(
this
.
B
)
return
buf
,
nil
}
func
(
this
*
EchoPackage
)
Unmarshal
(
buf
*
bytes
.
Buffer
)
(
int
,
error
)
{
var
(
err
error
len
byte
)
if
buf
.
Len
()
<
echoPkgHeaderLen
{
return
0
,
ErrNotEnoughStream
}
// header
err
=
binary
.
Read
(
buf
,
binary
.
LittleEndian
,
&
(
this
.
H
))
if
err
!=
nil
{
return
0
,
err
}
if
this
.
H
.
Magic
!=
echoPkgMagic
{
log
.
Error
(
"@this.H.Magic{%x}, right magic{%x}"
,
this
.
H
.
Magic
,
echoPkgMagic
)
return
0
,
ErrIllegalMagic
}
if
buf
.
Len
()
<
(
int
)(
this
.
H
.
Len
)
{
return
0
,
ErrNotEnoughStream
}
if
maxEchoStringLen
<
this
.
H
.
Len
-
1
{
return
0
,
ErrTooLargePackage
}
len
,
err
=
buf
.
ReadByte
()
if
err
!=
nil
{
return
0
,
nil
}
this
.
B
=
(
string
)(
buf
.
Next
((
int
)(
len
)))
return
(
int
)(
this
.
H
.
Len
)
+
echoPkgHeaderLen
,
nil
}
echo/udp-echo/client/app/handler.go
0 → 100644
View file @
bfb3fc6a
/******************************************************
# DESC : echo package handler
# AUTHOR : Alex Stocks
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-09-04 13:08
# FILE : handler.go
******************************************************/
package
main
import
(
"errors"
"time"
)
import
(
"github.com/AlexStocks/getty"
log
"github.com/AlexStocks/log4go"
)
var
(
errSessionNotExist
=
errors
.
New
(
"session not exist!"
)
)
////////////////////////////////////////////
// EchoMessageHandler
////////////////////////////////////////////
type
clientEchoSession
struct
{
session
getty
.
Session
reqNum
int32
}
type
EchoMessageHandler
struct
{
}
func
newEchoMessageHandler
()
*
EchoMessageHandler
{
return
&
EchoMessageHandler
{}
}
func
(
this
*
EchoMessageHandler
)
OnOpen
(
session
getty
.
Session
)
error
{
client
.
addSession
(
session
)
return
nil
}
func
(
this
*
EchoMessageHandler
)
OnError
(
session
getty
.
Session
,
err
error
)
{
log
.
Info
(
"session{%s} got error{%v}, will be closed."
,
session
.
Stat
(),
err
)
client
.
removeSession
(
session
)
}
func
(
this
*
EchoMessageHandler
)
OnClose
(
session
getty
.
Session
)
{
log
.
Info
(
"session{%s} is closing......"
,
session
.
Stat
())
client
.
removeSession
(
session
)
}
func
(
this
*
EchoMessageHandler
)
OnMessage
(
session
getty
.
Session
,
pkg
interface
{})
{
p
,
ok
:=
pkg
.
(
*
EchoPackage
)
if
!
ok
{
log
.
Error
(
"illegal packge{%#v}"
,
pkg
)
return
}
log
.
Debug
(
"get echo package{%s}"
,
p
)
client
.
updateSession
(
session
)
}
func
(
this
*
EchoMessageHandler
)
OnCron
(
session
getty
.
Session
)
{
clientEchoSession
,
err
:=
client
.
getClientEchoSession
(
session
)
if
err
!=
nil
{
log
.
Error
(
"client.getClientSession(session{%s}) = error{%#v}"
,
session
.
Stat
(),
err
)
return
}
if
conf
.
sessionTimeout
.
Nanoseconds
()
<
time
.
Since
(
session
.
GetActive
())
.
Nanoseconds
()
{
log
.
Warn
(
"session{%s} timeout{%s}, reqNum{%d}"
,
session
.
Stat
(),
time
.
Since
(
session
.
GetActive
())
.
String
(),
clientEchoSession
.
reqNum
)
client
.
removeSession
(
session
)
return
}
client
.
heartbeat
(
session
)
}
echo/udp-echo/client/app/main.go
0 → 100644
View file @
bfb3fc6a
/******************************************************
# DESC : echo client app
# AUTHOR : Alex Stocks
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-09-06 17:24
# FILE : main.go
******************************************************/
package
main
import
(
// "flag"
"fmt"
"net"
"net/http"
_
"net/http/pprof"
"os"
"os/signal"
// "strings"
"sync/atomic"
"syscall"
"time"
)
import
(
"github.com/AlexStocks/getty"
"github.com/AlexStocks/goext/log"
"github.com/AlexStocks/goext/net"
"github.com/AlexStocks/goext/time"
log
"github.com/AlexStocks/log4go"
)
const
(
pprofPath
=
"/debug/pprof/"
)
const
(
WritePkgTimeout
=
1e8
)
var
(
client
EchoClient
)
////////////////////////////////////////////////////////////////////
// main
////////////////////////////////////////////////////////////////////
func
main
()
{
initConf
()
initProfiling
()
initClient
()
gxlog
.
CInfo
(
"%s starts successfull! its version=%s
\n
"
,
conf
.
AppName
,
Version
)
log
.
Info
(
"%s starts successfull! its version=%s
\n
"
,
conf
.
AppName
,
Version
)
go
test
()
initSignal
()
}
func
initProfiling
()
{
var
(
addr
string
)
addr
=
gxnet
.
HostAddress
(
conf
.
LocalHost
,
conf
.
ProfilePort
)
log
.
Info
(
"App Profiling startup on address{%v}"
,
addr
+
pprofPath
)
go
func
()
{
log
.
Info
(
http
.
ListenAndServe
(
addr
,
nil
))
}()
}
func
newSession
(
session
getty
.
Session
)
error
{
var
(
ok
bool
udpConn
*
net
.
UDPConn
)
if
conf
.
GettySessionParam
.
CompressEncoding
{
session
.
SetCompressType
(
getty
.
CompressZip
)
}
if
udpConn
,
ok
=
session
.
Conn
()
.
(
*
net
.
UDPConn
);
!
ok
{
panic
(
fmt
.
Sprintf
(
"%s, session.conn{%#v} is not tcp connection
\n
"
,
session
.
Stat
(),
session
.
Conn
()))
}
udpConn
.
SetReadBuffer
(
conf
.
GettySessionParam
.
UdpRBufSize
)
udpConn
.
SetWriteBuffer
(
conf
.
GettySessionParam
.
UdpWBufSize
)
session
.
SetName
(
conf
.
GettySessionParam
.
SessionName
)
session
.
SetPkgHandler
(
NewEchoPackageHandler
())
session
.
SetEventListener
(
newEchoMessageHandler
())
session
.
SetRQLen
(
conf
.
GettySessionParam
.
PkgRQSize
)
session
.
SetWQLen
(
conf
.
GettySessionParam
.
PkgWQSize
)
session
.
SetReadTimeout
(
conf
.
GettySessionParam
.
udpReadTimeout
)
session
.
SetWriteTimeout
(
conf
.
GettySessionParam
.
udpWriteTimeout
)
session
.
SetCronPeriod
((
int
)(
conf
.
heartbeatPeriod
.
Nanoseconds
()
/
1e6
))
session
.
SetWaitTime
(
conf
.
GettySessionParam
.
waitTimeout
)
log
.
Debug
(
"client new session:%s
\n
"
,
session
.
Stat
())
return
nil
}
func
initClient
()
{
client
.
gettyClient
=
getty
.
NewUDPClient
(
(
int
)(
conf
.
ConnectionNum
),
conf
.
connectInterval
,
gxnet
.
HostAddress
(
conf
.
ServerHost
,
conf
.
ServerPort
),
)
client
.
gettyClient
.
RunEventLoop
(
newSession
)
}
func
uninitClient
()
{
client
.
close
()
}
func
initSignal
()
{
// signal.Notify的ch信道是阻塞的(signal.Notify不会阻塞发送信号), 需要设置缓冲
signals
:=
make
(
chan
os
.
Signal
,
1
)
// It is not possible to block SIGKILL or syscall.SIGSTOP
signal
.
Notify
(
signals
,
os
.
Interrupt
,
os
.
Kill
,
syscall
.
SIGHUP
,
syscall
.
SIGQUIT
,
syscall
.
SIGTERM
,
syscall
.
SIGINT
)
for
{
sig
:=
<-
signals
log
.
Info
(
"get signal %s"
,
sig
.
String
())
switch
sig
{
case
syscall
.
SIGHUP
:
// reload()
default
:
go
time
.
AfterFunc
(
conf
.
failFastTimeout
,
func
()
{
// log.Warn("app exit now by force...")
// os.Exit(1)
log
.
Exit
(
"app exit now by force..."
)
log
.
Close
()
})
// 要么survialTimeout时间内执行完毕下面的逻辑然后程序退出,要么执行上面的超时函数程序强行退出
uninitClient
()
// fmt.Println("app exit now...")
log
.
Exit
(
"app exit now..."
)
log
.
Close
()
return
}
}
}
func
echo
()
{
var
pkg
EchoPackage
pkg
.
H
.
Magic
=
echoPkgMagic
pkg
.
H
.
LogID
=
(
uint32
)(
src
.
Int63
())
pkg
.
H
.
Sequence
=
atomic
.
AddUint32
(
&
reqID
,
1
)
// pkg.H.ServiceID = 0
pkg
.
H
.
Command
=
echoCmd
pkg
.
B
=
conf
.
EchoString
pkg
.
H
.
Len
=
(
uint16
)(
len
(
pkg
.
B
))
+
1
if
session
:=
client
.
selectSession
();
session
!=
nil
{
err
:=
session
.
WritePkg
(
&
pkg
,
WritePkgTimeout
)
if
err
!=
nil
{
log
.
Warn
(
"session.WritePkg(session{%s}, pkg{%s}) = error{%v}"
,
session
.
Stat
(),
pkg
,
err
)
session
.
Close
()
client
.
removeSession
(
session
)
}
}
}
func
test
()
{
for
{
if
client
.
isAvailable
()
{
break
}
time
.
Sleep
(
1e6
)
}
var
(
cost
int64
counter
gxtime
.
CountWatch
)
counter
.
Start
()
for
i
:=
0
;
i
<
conf
.
EchoTimes
;
i
++
{
echo
()
}
cost
=
counter
.
Count
()
log
.
Info
(
"after loop %d times, echo cost %d ms"
,
conf
.
EchoTimes
,
cost
/
1e6
)
gxlog
.
CInfo
(
"after loop %d times, echo cost %d ms"
,
conf
.
EchoTimes
,
cost
/
1e6
)
}
echo/udp-echo/client/app/readwriter.go
0 → 100644
View file @
bfb3fc6a
/******************************************************
# DESC : echo stream parser
# AUTHOR : Alex Stocks
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-09-04 13:08
# FILE : readwriter.go
******************************************************/
package
main
import
(
"bytes"
"errors"
"time"
)
import
(
"github.com/AlexStocks/getty"
log
"github.com/AlexStocks/log4go"
)
type
EchoPackageHandler
struct
{
}
func
NewEchoPackageHandler
()
*
EchoPackageHandler
{
return
&
EchoPackageHandler
{}
}
func
(
this
*
EchoPackageHandler
)
Read
(
ss
getty
.
Session
,
data
[]
byte
)
(
interface
{},
int
,
error
)
{
var
(
err
error
len
int
pkg
EchoPackage
buf
*
bytes
.
Buffer
)
buf
=
bytes
.
NewBuffer
(
data
)
len
,
err
=
pkg
.
Unmarshal
(
buf
)
if
err
!=
nil
{
if
err
==
ErrNotEnoughStream
{
return
nil
,
0
,
nil
}
return
nil
,
0
,
err
}
return
&
pkg
,
len
,
nil
}
func
(
this
*
EchoPackageHandler
)
Write
(
ss
getty
.
Session
,
pkg
interface
{})
error
{
var
(
ok
bool
err
error
startTime
time
.
Time
echoPkg
*
EchoPackage
buf
*
bytes
.
Buffer
)
startTime
=
time
.
Now
()
if
echoPkg
,
ok
=
pkg
.
(
*
EchoPackage
);
!
ok
{
log
.
Error
(
"illegal pkg:%+v
\n
"
,
pkg
)
return
errors
.
New
(
"invalid echo package!"
)
}
buf
,
err
=
echoPkg
.
Marshal
()
if
err
!=
nil
{
log
.
Warn
(
"binary.Write(echoPkg{%#v}) = err{%#v}"
,
echoPkg
,
err
)
return
err
}
err
=
ss
.
WriteBytes
(
buf
.
Bytes
())
log
.
Info
(
"WriteEchoPkgTimeMs = %s"
,
time
.
Since
(
startTime
)
.
String
())
return
err
}
echo/udp-echo/client/app/version.go
0 → 100644
View file @
bfb3fc6a
/******************************************************
# DESC : echo client version
# MAINTAINER : Alex Stocks
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-09-06 11:23
# FILE : version.go
******************************************************/
package
main
var
(
Version
=
"0.8.1"
)
echo/udp-echo/client/assembly/bin/load.sh
0 → 100644
View file @
bfb3fc6a
#!/usr/bin/env bash
# ******************************************************
# DESC : getty app devops script
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : LGPL V3
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-05-13 02:01
# FILE : load.sh
# ******************************************************
APP_NAME
=
"APPLICATION_NAME"
APP_ARGS
=
""
PROJECT_HOME
=
""
OS_NAME
=
`
uname
`
if
[[
${
OS_NAME
}
==
"Linux"
]]
;
then
PROJECT_HOME
=
`
pwd
`
PROJECT_HOME
=
${
PROJECT_HOME
}
"/"
fi
export
APP_CONF_FILE
=
${
PROJECT_HOME
}
"TARGET_CONF_FILE"
export
APP_LOG_CONF_FILE
=
${
PROJECT_HOME
}
"TARGET_LOG_CONF_FILE"
usage
()
{
echo
"Usage:
$0
start"
echo
"
$0
stop"
echo
"
$0
term"
echo
"
$0
restart"
echo
"
$0
list"
exit
}
start
()
{
APP_LOG_PATH
=
${
PROJECT_HOME
}
"logs/"
mkdir
-p
${
APP_LOG_PATH
}
APP_BIN
=
${
PROJECT_HOME
}
sbin/
${
APP_NAME
}
chmod
u+x
${
APP_BIN
}
# CMD="nohup ${APP_BIN} ${APP_ARGS} >>${APP_NAME}.nohup.out 2>&1 &"
CMD
=
"
${
APP_BIN
}
"
eval
${
CMD
}
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{print $2}'
`
if
[[
${
OS_NAME
}
!=
"Linux"
]]
;
then
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{print $1}'
`
fi
if
[
"
${
PID
}
"
!=
""
]
;
then
for
p
in
${
PID
}
do
echo
"start
${
APP_NAME
}
( pid ="
${
p
}
")"
done
fi
}
stop
()
{
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{print $2}'
`
if
[[
${
OS_NAME
}
!=
"Linux"
]]
;
then
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{print $1}'
`
fi
if
[
"
${
PID
}
"
!=
""
]
;
then
for
ps
in
${
PID
}
do
echo
"kill -SIGINT
${
APP_NAME
}
( pid ="
${
ps
}
")"
kill
-2
${
ps
}
done
fi
}
term
()
{
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{print $2}'
`
if
[[
${
OS_NAME
}
!=
"Linux"
]]
;
then
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{print $1}'
`
fi
if
[
"
${
PID
}
"
!=
""
]
;
then
for
ps
in
${
PID
}
do
echo
"kill -9
${
APP_NAME
}
( pid ="
${
ps
}
")"
kill
-9
${
ps
}
done
fi
}
list
()
{
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{printf("%s,%s,%s,%s\n", $1, $2, $9, $10)}'
`
if
[[
${
OS_NAME
}
!=
"Linux"
]]
;
then
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{printf("%s,%s,%s,%s,%s\n", $1, $4, $6, $7, $8)}'
`
fi
if
[
"
${
PID
}
"
!=
""
]
;
then
echo
"list
${
APP_NAME
}
"
if
[[
${
OS_NAME
}
==
"Linux"
]]
;
then
echo
"index: user, pid, start, duration"
else
echo
"index: PID, WINPID, UID, STIME, COMMAND"
fi
idx
=
0
for
ps
in
${
PID
}
do
echo
"
${
idx
}
:
${
ps
}
"
((
idx ++
))
done
fi
}
opt
=
$1
case
C
"
$opt
"
in
Cstart
)
start
;;
Cstop
)
stop
;;
Cterm
)
term
;;
Crestart
)
term
start
;;
Clist
)
list
;;
C
*
)
usage
;;
esac
echo/udp-echo/client/assembly/common/app.properties
0 → 100644
View file @
bfb3fc6a
# getty application configure script
# ******************************************************
# DESC : application environment variable
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:29
# FILE : app.properties
# ******************************************************
TARGET_EXEC_NAME
=
"echo_client"
BUILD_PACKAGE
=
"app"
TARGET_CONF_FILE
=
"conf/config.toml"
TARGET_LOG_CONF_FILE
=
"conf/log.xml"
echo/udp-echo/client/assembly/common/build.sh
0 → 100644
View file @
bfb3fc6a
#!/usr/bin/env bash
# ******************************************************
# DESC : build script
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:28
# FILE : build.sh
# ******************************************************
rm
-rf
target/
PROJECT_HOME
=
`
pwd
`
TARGET_FOLDER
=
${
PROJECT_HOME
}
/target/
${
GOOS
}
TARGET_SBIN_NAME
=
${
TARGET_EXEC_NAME
}
version
=
`
cat
app/version.go |
grep
Version |
awk
-F
'='
'{print $2}'
|
awk
-F
'"'
'{print $2}'
`
if
[[
${
GOOS
}
==
"windows"
]]
;
then
TARGET_SBIN_NAME
=
${
TARGET_SBIN_NAME
}
.exe
fi
TARGET_NAME
=
${
TARGET_FOLDER
}
/
${
TARGET_SBIN_NAME
}
if
[[
$PROFILE
=
"test"
]]
;
then
# GFLAGS=-gcflags "-N -l" -race -x -v # -x会把go build的详细过程输出
# GFLAGS=-gcflags "-N -l" -race -v
# GFLAGS="-gcflags \"-N -l\" -v"
cd
${
BUILD_PACKAGE
}
&&
go build
-gcflags
"-N -l"
-x
-v
-i
-o
${
TARGET_NAME
}
&&
cd
-
else
# -s去掉符号表(然后panic时候的stack trace就没有任何文件名/行号信息了,这个等价于普通C/C++程序被strip的效果),
# -w去掉DWARF调试信息,得到的程序就不能用gdb调试了。-s和-w也可以分开使用,一般来说如果不打算用gdb调试,
# -w基本没啥损失。-s的损失就有点大了。
cd
${
BUILD_PACKAGE
}
&&
go build
-ldflags
"-w"
-x
-v
-i
-o
${
TARGET_NAME
}
&&
cd
-
fi
TAR_NAME
=
${
TARGET_EXEC_NAME
}
-
${
version
}
-
`
date
"+%Y%m%d-%H%M"
`
-
${
PROFILE
}
mkdir
-p
${
TARGET_FOLDER
}
/
${
TAR_NAME
}
SBIN_DIR
=
${
TARGET_FOLDER
}
/
${
TAR_NAME
}
/sbin
BIN_DIR
=
${
TARGET_FOLDER
}
/
${
TAR_NAME
}
CONF_DIR
=
${
TARGET_FOLDER
}
/
${
TAR_NAME
}
/conf
mkdir
-p
${
SBIN_DIR
}
mkdir
-p
${
CONF_DIR
}
mv
${
TARGET_NAME
}
${
SBIN_DIR
}
cp
-r
assembly/bin
${
BIN_DIR
}
# modify APPLICATION_NAME
# OS=`uname`
# if [[ $OS=="Darwin" ]]; then
if
[
"
$(
uname
)
"
==
"Darwin"
]
;
then
sed
-i
""
"s~APPLICATION_NAME~
${
TARGET_EXEC_NAME
}
~g"
${
BIN_DIR
}
/bin/
*
else
sed
-i
"s~APPLICATION_NAME~
${
TARGET_EXEC_NAME
}
~g"
${
BIN_DIR
}
/bin/
*
fi
# modify TARGET_CONF_FILE
if
[
"
$(
uname
)
"
==
"Darwin"
]
;
then
sed
-i
""
"s~TARGET_CONF_FILE~
${
TARGET_CONF_FILE
}
~g"
${
BIN_DIR
}
/bin/
*
else
sed
-i
"s~TARGET_CONF_FILE~
${
TARGET_CONF_FILE
}
~g"
${
BIN_DIR
}
/bin/
*
fi
# modify TARGET_LOG_CONF_FILE
if
[
"
$(
uname
)
"
==
"Darwin"
]
;
then
sed
-i
""
"s~TARGET_LOG_CONF_FILE~
${
TARGET_LOG_CONF_FILE
}
~g"
${
BIN_DIR
}
/bin/
*
else
sed
-i
"s~TARGET_LOG_CONF_FILE~
${
TARGET_LOG_CONF_FILE
}
~g"
${
BIN_DIR
}
/bin/
*
fi
cp
-r
profiles/
${
PROFILE
}
/
*
${
CONF_DIR
}
cd
${
TARGET_FOLDER
}
tar
czf
${
TAR_NAME
}
.tar.gz
${
TAR_NAME
}
/
*
echo/udp-echo/client/assembly/linux/test.sh
0 → 100644
View file @
bfb3fc6a
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for test env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : LGPL V3
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : test.sh
# ******************************************************
set
-e
export
GOOS
=
linux
export
GOARCH
=
amd64
PROFILE
=
test
PROJECT_HOME
=
`
pwd
`
if
[
-f
"
${
PROJECT_HOME
}
/assembly/common/app.properties"
]
;
then
.
${
PROJECT_HOME
}
/assembly/common/app.properties
fi
if
[
-f
"
${
PROJECT_HOME
}
/assembly/common/build.sh"
]
;
then
.
${
PROJECT_HOME
}
/assembly/common/build.sh
fi
echo/udp-echo/client/assembly/mac/test.sh
0 → 100644
View file @
bfb3fc6a
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for test env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : test.sh
# ******************************************************
set
-e
export
GOOS
=
darwin
export
GOARCH
=
amd64
PROFILE
=
test
PROJECT_HOME
=
`
pwd
`
if
[
-f
"
${
PROJECT_HOME
}
/assembly/common/app.properties"
]
;
then
.
${
PROJECT_HOME
}
/assembly/common/app.properties
fi
if
[
-f
"
${
PROJECT_HOME
}
/assembly/common/build.sh"
]
;
then
.
${
PROJECT_HOME
}
/assembly/common/build.sh
fi
echo/udp-echo/client/assembly/windows/test.sh
0 → 100644
View file @
bfb3fc6a
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for test env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : test.sh
# ******************************************************
set
-e
export
GOOS
=
windows
export
GOARCH
=
amd64
PROFILE
=
test
PROJECT_HOME
=
`
pwd
`
if
[
-f
"
${
PROJECT_HOME
}
/assembly/common/app.properties"
]
;
then
.
${
PROJECT_HOME
}
/assembly/common/app.properties
fi
if
[
-f
"
${
PROJECT_HOME
}
/assembly/common/build.sh"
]
;
then
.
${
PROJECT_HOME
}
/assembly/common/build.sh
fi
echo/udp-echo/client/profiles/test/config.toml
0 → 100644
View file @
bfb3fc6a
# toml configure file
# toml中key的首字母可以小写,但是对应的golang中的struct成员首字母必须大写
AppName
=
"ECHO-CLIENT"
# host
LocalHost
=
"127.0.0.1"
# server
# ServerHost = "192.168.8.3"
ServerHost
=
"127.0.0.1"
ServerPort
=
10000
ProfilePort
=
10080
# connection pool
# 连接池连接数目
ConnectionNum
=
2
# 当连接失败或者连接断开时,连接池中重连的间隔时间
ConnectInterval
=
"5s"
# session
# client与server之间连接的心跳周期
HeartbeatPeriod
=
"10s"
# client与server之间连接的超时时间
SessionTimeout
=
"20s"
# client
# client echo request string
EchoString
=
"Hello, getty!"
# 发送echo请求次数
EchoTimes
=
10000
# app fail fast
FailFastTimeout
=
"3s"
# tcp
[GettySessionParam]
CompressEncoding
=
true
UdpRBufSize
=
262144
UdpWBufSize
=
65536
PkgRQSize
=
512
PkgWQSize
=
256
UdpReadTimeout
=
"1s"
UdpWriteTimeout
=
"5s"
WaitTimeout
=
"1s"
SessionName
=
"echo-client"
echo/udp-echo/client/profiles/test/log.xml
0 → 100644
View file @
bfb3fc6a
<logging>
<filter
enabled=
"true"
>
<tag>
stdout
</tag>
<type>
console
</type>
<!-- level is (:?FINEST|FINE|DEBUG|TRACE|INFO|WARNING|ERROR) -->
<level>
DEBUG
</level>
</filter>
<filter
enabled=
"false"
>
<tag>
debug_file
</tag>
<type>
file
</type>
<level>
DEBUG
</level>
<property
name=
"filename"
>
logs/debug.log
</property>
<property
name=
"format"
>
[%D %T] [%L] [%S] %M
</property>
<property
name=
"rotate"
>
true
</property>
<!-- true enables log rotation, otherwise append -->
<property
name=
"maxsize"
>
0M
</property>
<!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property
name=
"maxlines"
>
0K
</property>
<!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property
name=
"daily"
>
true
</property>
<!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter
enabled=
"true"
>
<tag>
info_file
</tag>
<type>
file
</type>
<level>
INFO
</level>
<property
name=
"filename"
>
logs/info.log
</property>
<!--
%T - Time (15:04:05 MST)
%t - Time (15:04)
%D - Date (2006/01/02)
%d - Date (01/02/06)
%L - Level (FNST, FINE, DEBG, TRAC, WARN, EROR, CRIT)
%S - Source
%M - Message
It ignores unknown format strings (and removes them)
Recommended: "[%D %T] [%L] (%S) %M"
-->
<property
name=
"format"
>
[%D %T] [%L] [%S] %M
</property>
<property
name=
"rotate"
>
true
</property>
<!-- true enables log rotation, otherwise append -->
<property
name=
"maxsize"
>
0M
</property>
<!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property
name=
"maxlines"
>
0K
</property>
<!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property
name=
"daily"
>
true
</property>
<!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter
enabled=
"true"
>
<tag>
warn_file
</tag>
<type>
file
</type>
<level>
WARNING
</level>
<property
name=
"filename"
>
logs/warn.log
</property>
<property
name=
"format"
>
[%D %T] [%L] [%S] %M
</property>
<property
name=
"rotate"
>
true
</property>
<!-- true enables log rotation, otherwise append -->
<property
name=
"maxsize"
>
0M
</property>
<!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property
name=
"maxlines"
>
0K
</property>
<!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property
name=
"daily"
>
true
</property>
<!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter
enabled=
"true"
>
<tag>
error_file
</tag>
<type>
file
</type>
<level>
ERROR
</level>
<property
name=
"filename"
>
logs/error.log
</property>
<property
name=
"format"
>
[%D %T] [%L] [%S] %M
</property>
<property
name=
"rotate"
>
true
</property>
<!-- true enables log rotation, otherwise append -->
<property
name=
"maxsize"
>
0M
</property>
<!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property
name=
"maxlines"
>
0K
</property>
<!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property
name=
"daily"
>
true
</property>
<!-- Automatically rotates when a log message is written after midnight -->
</filter>
</logging>
echo/udp-echo/server/app/config.go
0 → 100644
View file @
bfb3fc6a
/******************************************************
# DESC : env var & configure
# MAINTAINER : Alex Stocks
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-09-06 16:53
# FILE : config.go
******************************************************/
package
main
import
(
"fmt"
"os"
"path"
"time"
)
import
(
log
"github.com/AlexStocks/log4go"
config
"github.com/koding/multiconfig"
)
const
(
APP_CONF_FILE
string
=
"APP_CONF_FILE"
APP_LOG_CONF_FILE
string
=
"APP_LOG_CONF_FILE"
)
var
(
conf
*
Config
)
type
(
GettySessionParam
struct
{
CompressEncoding
bool
`default:"false"`
UdpRBufSize
int
`default:"262144"`
UdpWBufSize
int
`default:"65536"`
PkgRQSize
int
`default:"1024"`
PkgWQSize
int
`default:"1024"`
UdpReadTimeout
string
`default:"1s"`
udpReadTimeout
time
.
Duration
UdpWriteTimeout
string
`default:"5s"`
udpWriteTimeout
time
.
Duration
WaitTimeout
string
`default:"7s"`
waitTimeout
time
.
Duration
SessionName
string
`default:"echo-client"`
}
// Config holds supported types by the multiconfig package
Config
struct
{
// local address
AppName
string
`default:"echo-server"`
Host
string
`default:"127.0.0.1"`
Ports
[]
string
`default:["10000"]`
ProfilePort
int
`default:"10086"`
// session
SessionTimeout
string
`default:"60s"`
sessionTimeout
time
.
Duration
SessionNumber
int
`default:"1000"`
// app
FailFastTimeout
string
`default:"5s"`
failFastTimeout
time
.
Duration
// session tcp parameters
GettySessionParam
GettySessionParam
`required:"true"`
}
)
func
initConf
()
{
var
(
err
error
confFile
string
)
// configure
confFile
=
os
.
Getenv
(
APP_CONF_FILE
)
if
confFile
==
""
{
panic
(
fmt
.
Sprintf
(
"application configure file name is nil"
))
return
// I know it is of no usage. Just Err Protection.
}
if
path
.
Ext
(
confFile
)
!=
".toml"
{
panic
(
fmt
.
Sprintf
(
"application configure file name{%v} suffix must be .toml"
,
confFile
))
return
}
conf
=
new
(
Config
)
config
.
MustLoadWithPath
(
confFile
,
conf
)
conf
.
sessionTimeout
,
err
=
time
.
ParseDuration
(
conf
.
SessionTimeout
)
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"time.ParseDuration(SessionTimeout{%#v}) = error{%v}"
,
conf
.
SessionTimeout
,
err
))
return
}
conf
.
failFastTimeout
,
err
=
time
.
ParseDuration
(
conf
.
FailFastTimeout
)
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"time.ParseDuration(FailFastTimeout{%#v}) = error{%v}"
,
conf
.
FailFastTimeout
,
err
))
return
}
conf
.
GettySessionParam
.
udpReadTimeout
,
err
=
time
.
ParseDuration
(
conf
.
GettySessionParam
.
UdpReadTimeout
)
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"time.ParseDuration(UdpReadTimeout{%#v}) = error{%v}"
,
conf
.
GettySessionParam
.
UdpReadTimeout
,
err
))
return
}
conf
.
GettySessionParam
.
udpWriteTimeout
,
err
=
time
.
ParseDuration
(
conf
.
GettySessionParam
.
UdpWriteTimeout
)
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"time.ParseDuration(UdpWriteTimeout{%#v}) = error{%v}"
,
conf
.
GettySessionParam
.
UdpWriteTimeout
,
err
))
return
}
conf
.
GettySessionParam
.
waitTimeout
,
err
=
time
.
ParseDuration
(
conf
.
GettySessionParam
.
WaitTimeout
)
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"time.ParseDuration(WaitTimeout{%#v}) = error{%v}"
,
conf
.
GettySessionParam
.
WaitTimeout
,
err
))
return
}
// gxlog.CInfo("config{%#v}\n", conf)
// log
confFile
=
os
.
Getenv
(
APP_LOG_CONF_FILE
)
if
confFile
==
""
{
panic
(
fmt
.
Sprintf
(
"log configure file name is nil"
))
return
}
if
path
.
Ext
(
confFile
)
!=
".xml"
{
panic
(
fmt
.
Sprintf
(
"log configure file name{%v} suffix must be .xml"
,
confFile
))
return
}
log
.
LoadConfiguration
(
confFile
)
log
.
Info
(
"config{%#v}"
,
conf
)
return
}
echo/udp-echo/server/app/echo.go
0 → 100644
View file @
bfb3fc6a
/******************************************************
# DESC : echo package
# AUTHOR : Alex Stocks
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-08-22 17:44
# FILE : echo.go
******************************************************/
package
main
import
(
"bytes"
"encoding/binary"
"errors"
"fmt"
"unsafe"
)
import
(
log
"github.com/AlexStocks/log4go"
)
////////////////////////////////////////////
// echo command
////////////////////////////////////////////
type
echoCommand
uint32
const
(
heartbeatCmd
=
iota
echoCmd
)
var
echoCommandStrings
=
[
...
]
string
{
"heartbeat"
,
"echo"
,
}
func
(
c
echoCommand
)
String
()
string
{
return
echoCommandStrings
[
c
]
}
////////////////////////////////////////////
// EchoPkgHandler
////////////////////////////////////////////
const
(
echoPkgMagic
=
0x20160905
maxEchoStringLen
=
0xff
echoHeartbeatRequestString
=
"ping"
echoHeartbeatResponseString
=
"pong"
)
var
(
ErrNotEnoughStream
=
errors
.
New
(
"packet stream is not enough"
)
ErrTooLargePackage
=
errors
.
New
(
"package length is exceed the echo package's legal maximum length."
)
ErrIllegalMagic
=
errors
.
New
(
"package magic is not right."
)
)
var
(
echoPkgHeaderLen
int
)
func
init
()
{
echoPkgHeaderLen
=
(
int
)((
uint
)(
unsafe
.
Sizeof
(
EchoPkgHeader
{})))
}
type
EchoPkgHeader
struct
{
Magic
uint32
LogID
uint32
// log id
Sequence
uint32
// request/response sequence
ServiceID
uint32
// service id
Command
uint32
// operation command code
Code
int32
// error code
Len
uint16
// body length
_
uint16
_
int32
// reserved, maybe used as package md5 checksum
}
type
EchoPackage
struct
{
H
EchoPkgHeader
B
string
}
func
(
this
EchoPackage
)
String
()
string
{
return
fmt
.
Sprintf
(
"log id:%d, sequence:%d, command:%s, echo string:%s"
,
this
.
H
.
LogID
,
this
.
H
.
Sequence
,
(
echoCommand
(
this
.
H
.
Command
))
.
String
(),
this
.
B
)
}
func
(
this
EchoPackage
)
Marshal
()
(
*
bytes
.
Buffer
,
error
)
{
var
(
err
error
buf
*
bytes
.
Buffer
)
buf
=
&
bytes
.
Buffer
{}
err
=
binary
.
Write
(
buf
,
binary
.
LittleEndian
,
this
.
H
)
if
err
!=
nil
{
return
nil
,
err
}
buf
.
WriteByte
((
byte
)(
len
(
this
.
B
)))
buf
.
WriteString
(
this
.
B
)
return
buf
,
nil
}
func
(
this
*
EchoPackage
)
Unmarshal
(
buf
*
bytes
.
Buffer
)
(
int
,
error
)
{
var
(
err
error
len
byte
)
if
buf
.
Len
()
<
echoPkgHeaderLen
{
return
0
,
ErrNotEnoughStream
}
// header
err
=
binary
.
Read
(
buf
,
binary
.
LittleEndian
,
&
(
this
.
H
))
if
err
!=
nil
{
return
0
,
err
}
if
this
.
H
.
Magic
!=
echoPkgMagic
{
log
.
Error
(
"@this.H.Magic{%x}, right magic{%x}"
,
this
.
H
.
Magic
,
echoPkgMagic
)
return
0
,
ErrIllegalMagic
}
if
buf
.
Len
()
<
(
int
)(
this
.
H
.
Len
)
{
return
0
,
ErrNotEnoughStream
}
// 防止恶意客户端把这个字段设置过大导致服务端死等或者服务端在准备对应的缓冲区时内存崩溃
if
maxEchoStringLen
<
this
.
H
.
Len
-
1
{
return
0
,
ErrTooLargePackage
}
len
,
err
=
buf
.
ReadByte
()
if
err
!=
nil
{
return
0
,
nil
}
this
.
B
=
(
string
)(
buf
.
Next
((
int
)(
len
)))
return
(
int
)(
this
.
H
.
Len
)
+
echoPkgHeaderLen
,
nil
}
echo/udp-echo/server/app/handler.go
0 → 100644
View file @
bfb3fc6a
/******************************************************
# DESC : echo package handler
# AUTHOR : Alex Stocks
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-09-04 13:08
# FILE : handler.go
******************************************************/
package
main
import
(
"errors"
"sync"
"time"
)
import
(
"github.com/AlexStocks/getty"
log
"github.com/AlexStocks/log4go"
)
const
(
WritePkgTimeout
=
1e8
)
var
(
errTooManySessions
=
errors
.
New
(
"Too many echo sessions!"
)
)
type
PackageHandler
interface
{
Handle
(
getty
.
Session
,
*
EchoPackage
)
error
}
////////////////////////////////////////////
// heartbeat handler
////////////////////////////////////////////
type
HeartbeatHandler
struct
{}
func
(
this
*
HeartbeatHandler
)
Handle
(
session
getty
.
Session
,
pkg
*
EchoPackage
)
error
{
log
.
Debug
(
"get echo heartbeat package{%s}"
,
pkg
)
var
rspPkg
EchoPackage
rspPkg
.
H
=
pkg
.
H
rspPkg
.
B
=
echoHeartbeatResponseString
rspPkg
.
H
.
Len
=
uint16
(
len
(
rspPkg
.
B
)
+
1
)
return
session
.
WritePkg
(
&
rspPkg
,
WritePkgTimeout
)
}
////////////////////////////////////////////
// message handler
////////////////////////////////////////////
type
MessageHandler
struct
{}
func
(
this
*
MessageHandler
)
Handle
(
session
getty
.
Session
,
pkg
*
EchoPackage
)
error
{
log
.
Debug
(
"get echo package{%s}"
,
pkg
)
return
session
.
WritePkg
(
pkg
,
WritePkgTimeout
)
}
////////////////////////////////////////////
// EchoMessageHandler
////////////////////////////////////////////
type
clientEchoSession
struct
{
session
getty
.
Session
active
time
.
Time
reqNum
int32
}
type
EchoMessageHandler
struct
{
handlers
map
[
uint32
]
PackageHandler
rwlock
sync
.
RWMutex
sessionMap
map
[
getty
.
Session
]
*
clientEchoSession
}
func
newEchoMessageHandler
()
*
EchoMessageHandler
{
handlers
:=
make
(
map
[
uint32
]
PackageHandler
)
handlers
[
heartbeatCmd
]
=
&
HeartbeatHandler
{}
handlers
[
echoCmd
]
=
&
MessageHandler
{}
return
&
EchoMessageHandler
{
sessionMap
:
make
(
map
[
getty
.
Session
]
*
clientEchoSession
),
handlers
:
handlers
}
}
func
(
this
*
EchoMessageHandler
)
OnOpen
(
session
getty
.
Session
)
error
{
var
(
err
error
)
this
.
rwlock
.
RLock
()
if
conf
.
SessionNumber
<
len
(
this
.
sessionMap
)
{
err
=
errTooManySessions
}
this
.
rwlock
.
RUnlock
()
if
err
!=
nil
{
return
err
}
log
.
Info
(
"got session:%s"
,
session
.
Stat
())
this
.
rwlock
.
Lock
()
this
.
sessionMap
[
session
]
=
&
clientEchoSession
{
session
:
session
}
this
.
rwlock
.
Unlock
()
return
nil
}
func
(
this
*
EchoMessageHandler
)
OnError
(
session
getty
.
Session
,
err
error
)
{
log
.
Info
(
"session{%s} got error{%v}, will be closed."
,
session
.
Stat
(),
err
)
this
.
rwlock
.
Lock
()
delete
(
this
.
sessionMap
,
session
)
this
.
rwlock
.
Unlock
()
}
func
(
this
*
EchoMessageHandler
)
OnClose
(
session
getty
.
Session
)
{
log
.
Info
(
"session{%s} is closing......"
,
session
.
Stat
())
this
.
rwlock
.
Lock
()
delete
(
this
.
sessionMap
,
session
)
this
.
rwlock
.
Unlock
()
}
func
(
this
*
EchoMessageHandler
)
OnMessage
(
session
getty
.
Session
,
pkg
interface
{})
{
p
,
ok
:=
pkg
.
(
*
EchoPackage
)
if
!
ok
{
log
.
Error
(
"illegal packge{%#v}"
,
pkg
)
return
}
handler
,
ok
:=
this
.
handlers
[
p
.
H
.
Command
]
if
!
ok
{
log
.
Error
(
"illegal command{%d}"
,
p
.
H
.
Command
)
return
}
err
:=
handler
.
Handle
(
session
,
p
)
if
err
!=
nil
{
this
.
rwlock
.
Lock
()
if
_
,
ok
:=
this
.
sessionMap
[
session
];
ok
{
this
.
sessionMap
[
session
]
.
active
=
time
.
Now
()
this
.
sessionMap
[
session
]
.
reqNum
++
}
this
.
rwlock
.
Unlock
()
}
}
func
(
this
*
EchoMessageHandler
)
OnCron
(
session
getty
.
Session
)
{
var
(
flag
bool
active
time
.
Time
)
this
.
rwlock
.
RLock
()
if
_
,
ok
:=
this
.
sessionMap
[
session
];
ok
{
active
=
session
.
GetActive
()
if
conf
.
sessionTimeout
.
Nanoseconds
()
<
time
.
Since
(
active
)
.
Nanoseconds
()
{
flag
=
true
log
.
Warn
(
"session{%s} timeout{%s}, reqNum{%d}"
,
session
.
Stat
(),
time
.
Since
(
active
)
.
String
(),
this
.
sessionMap
[
session
]
.
reqNum
)
}
}
this
.
rwlock
.
RUnlock
()
if
flag
{
this
.
rwlock
.
Lock
()
delete
(
this
.
sessionMap
,
session
)
this
.
rwlock
.
Unlock
()
session
.
Close
()
}
}
echo/udp-echo/server/app/readwriter.go
0 → 100644
View file @
bfb3fc6a
/******************************************************
# DESC : echo stream parser
# AUTHOR : Alex Stocks
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-09-04 13:08
# FILE : readwriter.go
******************************************************/
package
main
import
(
"bytes"
"errors"
"time"
)
import
(
"github.com/AlexStocks/getty"
log
"github.com/AlexStocks/log4go"
)
type
EchoPackageHandler
struct
{
}
func
NewEchoPackageHandler
()
*
EchoPackageHandler
{
return
&
EchoPackageHandler
{}
}
func
(
this
*
EchoPackageHandler
)
Read
(
ss
getty
.
Session
,
data
[]
byte
)
(
interface
{},
int
,
error
)
{
var
(
err
error
len
int
pkg
EchoPackage
buf
*
bytes
.
Buffer
)
buf
=
bytes
.
NewBuffer
(
data
)
len
,
err
=
pkg
.
Unmarshal
(
buf
)
if
err
!=
nil
{
if
err
==
ErrNotEnoughStream
{
return
nil
,
0
,
nil
}
return
nil
,
0
,
err
}
return
&
pkg
,
len
,
nil
}
func
(
this
*
EchoPackageHandler
)
Write
(
ss
getty
.
Session
,
pkg
interface
{})
error
{
var
(
ok
bool
err
error
startTime
time
.
Time
echoPkg
*
EchoPackage
buf
*
bytes
.
Buffer
)
startTime
=
time
.
Now
()
if
echoPkg
,
ok
=
pkg
.
(
*
EchoPackage
);
!
ok
{
log
.
Error
(
"illegal pkg:%+v
\n
"
,
pkg
)
return
errors
.
New
(
"invalid echo package!"
)
}
buf
,
err
=
echoPkg
.
Marshal
()
if
err
!=
nil
{
log
.
Warn
(
"binary.Write(echoPkg{%#v}) = err{%#v}"
,
echoPkg
,
err
)
return
err
}
err
=
ss
.
WriteBytes
(
buf
.
Bytes
())
log
.
Info
(
"WriteEchoPkgTimeMs = %s"
,
time
.
Since
(
startTime
)
.
String
())
return
err
}
echo/udp-echo/server/app/server.go
0 → 100644
View file @
bfb3fc6a
/******************************************************
# DESC : echo server
# AUTHOR : Alex Stocks
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-09-04 15:49
# FILE : server.go
******************************************************/
package
main
import
(
// "flag"
"fmt"
"net"
"net/http"
_
"net/http/pprof"
"os"
"os/signal"
// "strings"
"syscall"
"time"
)
import
(
"github.com/AlexStocks/getty"
"github.com/AlexStocks/goext/log"
"github.com/AlexStocks/goext/net"
log
"github.com/AlexStocks/log4go"
)
const
(
pprofPath
=
"/debug/pprof/"
)
var
(
// host = flag.String("host", "127.0.0.1", "local host address that server app will use")
// ports = flag.String("ports", "12345,12346,12347", "local host port list that the server app will bind")
)
var
(
serverList
[]
*
getty
.
Server
)
func
main
()
{
// flag.Parse()
// if *host == "" || *ports == "" {
// panic(fmt.Sprintf("Please intput local host ip or port lists"))
// }
initConf
()
initProfiling
()
initServer
()
gxlog
.
CInfo
(
"%s starts successfull! its version=%s, its listen ends=%s:%s
\n
"
,
conf
.
AppName
,
Version
,
conf
.
Host
,
conf
.
Ports
)
log
.
Info
(
"%s starts successfull! its version=%s, its listen ends=%s:%s
\n
"
,
conf
.
AppName
,
Version
,
conf
.
Host
,
conf
.
Ports
)
initSignal
()
}
func
initProfiling
()
{
var
(
addr
string
)
// addr = *host + ":" + "10000"
addr
=
gxnet
.
HostAddress
(
conf
.
Host
,
conf
.
ProfilePort
)
log
.
Info
(
"App Profiling startup on address{%v}"
,
addr
+
pprofPath
)
go
func
()
{
log
.
Info
(
http
.
ListenAndServe
(
addr
,
nil
))
}()
}
func
newSession
(
session
getty
.
Session
)
error
{
var
(
ok
bool
udpConn
*
net
.
UDPConn
)
if
conf
.
GettySessionParam
.
CompressEncoding
{
session
.
SetCompressType
(
getty
.
CompressZip
)
}
gxlog
.
CInfo
(
"session:%#v"
,
session
)
if
udpConn
,
ok
=
session
.
Conn
()
.
(
*
net
.
UDPConn
);
!
ok
{
panic
(
fmt
.
Sprintf
(
"%s, session.conn{%#v} is not udp connection
\n
"
,
session
.
Stat
(),
session
.
Conn
()))
}
udpConn
.
SetReadBuffer
(
conf
.
GettySessionParam
.
UdpRBufSize
)
udpConn
.
SetWriteBuffer
(
conf
.
GettySessionParam
.
UdpWBufSize
)
session
.
SetName
(
conf
.
GettySessionParam
.
SessionName
)
session
.
SetPkgHandler
(
NewEchoPackageHandler
())
session
.
SetEventListener
(
newEchoMessageHandler
())
session
.
SetRQLen
(
conf
.
GettySessionParam
.
PkgRQSize
)
session
.
SetWQLen
(
conf
.
GettySessionParam
.
PkgWQSize
)
session
.
SetReadTimeout
(
conf
.
GettySessionParam
.
udpReadTimeout
)
session
.
SetWriteTimeout
(
conf
.
GettySessionParam
.
udpWriteTimeout
)
session
.
SetCronPeriod
((
int
)(
conf
.
sessionTimeout
.
Nanoseconds
()
/
1e6
))
session
.
SetWaitTime
(
conf
.
GettySessionParam
.
waitTimeout
)
log
.
Debug
(
"app accepts new session:%s
\n
"
,
session
.
Stat
())
return
nil
}
func
initServer
()
{
var
(
addr
string
portList
[]
string
server
*
getty
.
Server
)
// if *host == "" {
// panic("host can not be nil")
// }
// if *ports == "" {
// panic("ports can not be nil")
// }
// portList = strings.Split(*ports, ",")
portList
=
conf
.
Ports
if
len
(
portList
)
==
0
{
panic
(
"portList is nil"
)
}
for
_
,
port
:=
range
portList
{
addr
=
gxnet
.
HostAddress2
(
conf
.
Host
,
port
)
server
=
getty
.
NewUDPPServer
(
addr
)
// run server
server
.
RunEventloop
(
newSession
)
log
.
Debug
(
"server bind addr{%s} ok!"
,
addr
)
serverList
=
append
(
serverList
,
server
)
}
}
func
uninitServer
()
{
for
_
,
server
:=
range
serverList
{
server
.
Close
()
}
}
func
initSignal
()
{
// signal.Notify的ch信道是阻塞的(signal.Notify不会阻塞发送信号), 需要设置缓冲
signals
:=
make
(
chan
os
.
Signal
,
1
)
// It is not possible to block SIGKILL or syscall.SIGSTOP
signal
.
Notify
(
signals
,
os
.
Interrupt
,
os
.
Kill
,
syscall
.
SIGHUP
,
syscall
.
SIGQUIT
,
syscall
.
SIGTERM
,
syscall
.
SIGINT
)
for
{
sig
:=
<-
signals
log
.
Info
(
"get signal %s"
,
sig
.
String
())
switch
sig
{
case
syscall
.
SIGHUP
:
// reload()
default
:
go
time
.
AfterFunc
(
conf
.
failFastTimeout
,
func
()
{
// log.Warn("app exit now by force...")
// os.Exit(1)
log
.
Exit
(
"app exit now by force..."
)
log
.
Close
()
})
// 要么survialTimeout时间内执行完毕下面的逻辑然后程序退出,要么执行上面的超时函数程序强行退出
uninitServer
()
// fmt.Println("app exit now...")
log
.
Exit
(
"app exit now..."
)
log
.
Close
()
return
}
}
}
echo/udp-echo/server/app/version.go
0 → 100644
View file @
bfb3fc6a
/******************************************************
# DESC : echo server version
# MAINTAINER : Alex Stocks
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-09-06 11:23
# FILE : version.go
******************************************************/
package
main
var
(
Version
=
"0.8.1"
)
echo/udp-echo/server/assembly/bin/load.sh
0 → 100644
View file @
bfb3fc6a
#!/usr/bin/env bash
# ******************************************************
# DESC : getty app devops script
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : LGPL V3
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-05-13 02:01
# FILE : load.sh
# ******************************************************
APP_NAME
=
"APPLICATION_NAME"
APP_ARGS
=
""
PROJECT_HOME
=
""
OS_NAME
=
`
uname
`
if
[[
${
OS_NAME
}
==
"Linux"
]]
;
then
PROJECT_HOME
=
`
pwd
`
PROJECT_HOME
=
${
PROJECT_HOME
}
"/"
fi
export
APP_CONF_FILE
=
${
PROJECT_HOME
}
"TARGET_CONF_FILE"
export
APP_LOG_CONF_FILE
=
${
PROJECT_HOME
}
"TARGET_LOG_CONF_FILE"
usage
()
{
echo
"Usage:
$0
start"
echo
"
$0
stop"
echo
"
$0
term"
echo
"
$0
restart"
echo
"
$0
list"
exit
}
start
()
{
APP_LOG_PATH
=
${
PROJECT_HOME
}
"logs/"
mkdir
-p
${
APP_LOG_PATH
}
APP_BIN
=
${
PROJECT_HOME
}
sbin/
${
APP_NAME
}
chmod
u+x
${
APP_BIN
}
# CMD="nohup ${APP_BIN} ${APP_ARGS} >>${APP_NAME}.nohup.out 2>&1 &"
CMD
=
"
${
APP_BIN
}
"
eval
${
CMD
}
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{print $2}'
`
if
[[
${
OS_NAME
}
!=
"Linux"
]]
;
then
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{print $1}'
`
fi
if
[
"
${
PID
}
"
!=
""
]
;
then
for
p
in
${
PID
}
do
echo
"start
${
APP_NAME
}
( pid ="
${
p
}
")"
done
fi
}
stop
()
{
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{print $2}'
`
if
[[
${
OS_NAME
}
!=
"Linux"
]]
;
then
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{print $1}'
`
fi
if
[
"
${
PID
}
"
!=
""
]
;
then
for
ps
in
${
PID
}
do
echo
"kill -SIGINT
${
APP_NAME
}
( pid ="
${
ps
}
")"
kill
-2
${
ps
}
done
fi
}
term
()
{
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{print $2}'
`
if
[[
${
OS_NAME
}
!=
"Linux"
]]
;
then
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{print $1}'
`
fi
if
[
"
${
PID
}
"
!=
""
]
;
then
for
ps
in
${
PID
}
do
echo
"kill -9
${
APP_NAME
}
( pid ="
${
ps
}
")"
kill
-9
${
ps
}
done
fi
}
list
()
{
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{printf("%s,%s,%s,%s\n", $1, $2, $9, $10)}'
`
if
[[
${
OS_NAME
}
!=
"Linux"
]]
;
then
PID
=
`
ps aux |
grep
-w
${
APP_NAME
}
|
grep
-v
grep
|
awk
'{printf("%s,%s,%s,%s,%s\n", $1, $4, $6, $7, $8)}'
`
fi
if
[
"
${
PID
}
"
!=
""
]
;
then
echo
"list
${
APP_NAME
}
"
if
[[
${
OS_NAME
}
==
"Linux"
]]
;
then
echo
"index: user, pid, start, duration"
else
echo
"index: PID, WINPID, UID, STIME, COMMAND"
fi
idx
=
0
for
ps
in
${
PID
}
do
echo
"
${
idx
}
:
${
ps
}
"
((
idx ++
))
done
fi
}
opt
=
$1
case
C
"
$opt
"
in
Cstart
)
start
;;
Cstop
)
stop
;;
Cterm
)
term
;;
Crestart
)
term
start
;;
Clist
)
list
;;
C
*
)
usage
;;
esac
echo/udp-echo/server/assembly/common/app.properties
0 → 100644
View file @
bfb3fc6a
# getty application configure script
# ******************************************************
# DESC : application environment variable
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:29
# FILE : app.properties
# ******************************************************
TARGET_EXEC_NAME
=
"echo_server"
BUILD_PACKAGE
=
"app"
TARGET_CONF_FILE
=
"conf/config.toml"
TARGET_LOG_CONF_FILE
=
"conf/log.xml"
echo/udp-echo/server/assembly/common/build.sh
0 → 100644
View file @
bfb3fc6a
#!/usr/bin/env bash
# ******************************************************
# DESC : build script
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:28
# FILE : build.sh
# ******************************************************
rm
-rf
target/
PROJECT_HOME
=
`
pwd
`
TARGET_FOLDER
=
${
PROJECT_HOME
}
/target/
${
GOOS
}
TARGET_SBIN_NAME
=
${
TARGET_EXEC_NAME
}
version
=
`
cat
app/version.go |
grep
Version |
awk
-F
'='
'{print $2}'
|
awk
-F
'"'
'{print $2}'
`
if
[[
${
GOOS
}
==
"windows"
]]
;
then
TARGET_SBIN_NAME
=
${
TARGET_SBIN_NAME
}
.exe
fi
TARGET_NAME
=
${
TARGET_FOLDER
}
/
${
TARGET_SBIN_NAME
}
if
[[
$PROFILE
=
"test"
]]
;
then
# GFLAGS=-gcflags "-N -l" -race -x -v # -x会把go build的详细过程输出
# GFLAGS=-gcflags "-N -l" -race -v
# GFLAGS="-gcflags \"-N -l\" -v"
cd
${
BUILD_PACKAGE
}
&&
go build
-gcflags
"-N -l"
-x
-v
-i
-o
${
TARGET_NAME
}
&&
cd
-
else
# -s去掉符号表(然后panic时候的stack trace就没有任何文件名/行号信息了,这个等价于普通C/C++程序被strip的效果),
# -w去掉DWARF调试信息,得到的程序就不能用gdb调试了。-s和-w也可以分开使用,一般来说如果不打算用gdb调试,
# -w基本没啥损失。-s的损失就有点大了。
cd
${
BUILD_PACKAGE
}
&&
go build
-ldflags
"-w"
-x
-v
-i
-o
${
TARGET_NAME
}
&&
cd
-
fi
TAR_NAME
=
${
TARGET_EXEC_NAME
}
-
${
version
}
-
`
date
"+%Y%m%d-%H%M"
`
-
${
PROFILE
}
mkdir
-p
${
TARGET_FOLDER
}
/
${
TAR_NAME
}
SBIN_DIR
=
${
TARGET_FOLDER
}
/
${
TAR_NAME
}
/sbin
BIN_DIR
=
${
TARGET_FOLDER
}
/
${
TAR_NAME
}
CONF_DIR
=
${
TARGET_FOLDER
}
/
${
TAR_NAME
}
/conf
mkdir
-p
${
SBIN_DIR
}
mkdir
-p
${
CONF_DIR
}
mv
${
TARGET_NAME
}
${
SBIN_DIR
}
cp
-r
assembly/bin
${
BIN_DIR
}
# modify APPLICATION_NAME
if
[
"
$(
uname
)
"
==
"Darwin"
]
;
then
sed
-i
""
"s~APPLICATION_NAME~
${
TARGET_EXEC_NAME
}
~g"
${
BIN_DIR
}
/bin/
*
else
sed
-i
"s~APPLICATION_NAME~
${
TARGET_EXEC_NAME
}
~g"
${
BIN_DIR
}
/bin/
*
fi
# modify TARGET_CONF_FILE
if
[
"
$(
uname
)
"
==
"Darwin"
]
;
then
sed
-i
""
"s~TARGET_CONF_FILE~
${
TARGET_CONF_FILE
}
~g"
${
BIN_DIR
}
/bin/
*
else
sed
-i
"s~TARGET_CONF_FILE~
${
TARGET_CONF_FILE
}
~g"
${
BIN_DIR
}
/bin/
*
fi
# modify TARGET_LOG_CONF_FILE
if
[
"
$(
uname
)
"
==
"Darwin"
]
;
then
sed
-i
""
"s~TARGET_LOG_CONF_FILE~
${
TARGET_LOG_CONF_FILE
}
~g"
${
BIN_DIR
}
/bin/
*
else
sed
-i
"s~TARGET_LOG_CONF_FILE~
${
TARGET_LOG_CONF_FILE
}
~g"
${
BIN_DIR
}
/bin/
*
fi
cp
-r
profiles/
${
PROFILE
}
/
*
${
CONF_DIR
}
cd
${
TARGET_FOLDER
}
tar
czf
${
TAR_NAME
}
.tar.gz
${
TAR_NAME
}
/
*
echo/udp-echo/server/assembly/linux/test.sh
0 → 100644
View file @
bfb3fc6a
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for test env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : LGPL V3
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : test.sh
# ******************************************************
set
-e
export
GOOS
=
linux
export
GOARCH
=
amd64
PROFILE
=
test
PROJECT_HOME
=
`
pwd
`
if
[
-f
"
${
PROJECT_HOME
}
/assembly/common/app.properties"
]
;
then
.
${
PROJECT_HOME
}
/assembly/common/app.properties
fi
if
[
-f
"
${
PROJECT_HOME
}
/assembly/common/build.sh"
]
;
then
.
${
PROJECT_HOME
}
/assembly/common/build.sh
fi
echo/udp-echo/server/assembly/mac/test.sh
0 → 100644
View file @
bfb3fc6a
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for test env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : test.sh
# ******************************************************
set
-e
export
GOOS
=
darwin
export
GOARCH
=
amd64
PROFILE
=
test
PROJECT_HOME
=
`
pwd
`
if
[
-f
"
${
PROJECT_HOME
}
/assembly/common/app.properties"
]
;
then
.
${
PROJECT_HOME
}
/assembly/common/app.properties
fi
if
[
-f
"
${
PROJECT_HOME
}
/assembly/common/build.sh"
]
;
then
.
${
PROJECT_HOME
}
/assembly/common/build.sh
fi
echo/udp-echo/server/assembly/windows/test.sh
0 → 100644
View file @
bfb3fc6a
#!/usr/bin/env bash
# ******************************************************
# DESC : build script for test env
# AUTHOR : Alex Stocks
# VERSION : 1.0
# LICENCE : Apache License 2.0
# EMAIL : alexstocks@foxmail.com
# MOD : 2016-07-12 16:34
# FILE : test.sh
# ******************************************************
set
-e
export
GOOS
=
windows
export
GOARCH
=
amd64
PROFILE
=
test
PROJECT_HOME
=
`
pwd
`
if
[
-f
"
${
PROJECT_HOME
}
/assembly/common/app.properties"
]
;
then
.
${
PROJECT_HOME
}
/assembly/common/app.properties
fi
if
[
-f
"
${
PROJECT_HOME
}
/assembly/common/build.sh"
]
;
then
.
${
PROJECT_HOME
}
/assembly/common/build.sh
fi
echo/udp-echo/server/profiles/test/config.toml
0 → 100644
View file @
bfb3fc6a
# toml configure file
# toml中key的首字母可以小写,但是对应的golang中的struct成员首字母必须大写
AppName
=
"ECHO-SERVER"
Host
=
"127.0.0.1"
# Host = "192.168.35.1"
# Host = "192.168.8.3"
Ports
=
[
"10000"
,
"20000"
]
ProfilePort
=
10086
# session
# client与server之间连接的超时时间
SessionTimeout
=
"20s"
SessionNumber
=
700
# app
FailFastTimeout
=
"3s"
# tcp
[GettySessionParam]
CompressEncoding
=
true
UdpRBufSize
=
262144
UdpWBufSize
=
524288
PkgRQSize
=
1024
PkgWQSize
=
512
UdpReadTimeout
=
"1s"
UdpWriteTimeout
=
"5s"
WaitTimeout
=
"1s"
SessionName
=
"echo-server"
echo/udp-echo/server/profiles/test/log.xml
0 → 100644
View file @
bfb3fc6a
<logging>
<filter
enabled=
"true"
>
<tag>
stdout
</tag>
<type>
console
</type>
<!-- level is (:?FINEST|FINE|DEBUG|TRACE|INFO|WARNING|ERROR) -->
<level>
DEBUG
</level>
</filter>
<filter
enabled=
"false"
>
<tag>
debug_file
</tag>
<type>
file
</type>
<level>
DEBUG
</level>
<property
name=
"filename"
>
logs/debug.log
</property>
<property
name=
"format"
>
[%D %T] [%L] [%S] %M
</property>
<property
name=
"rotate"
>
true
</property>
<!-- true enables log rotation, otherwise append -->
<property
name=
"maxsize"
>
0M
</property>
<!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property
name=
"maxlines"
>
0K
</property>
<!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property
name=
"daily"
>
true
</property>
<!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter
enabled=
"true"
>
<tag>
info_file
</tag>
<type>
file
</type>
<level>
INFO
</level>
<property
name=
"filename"
>
logs/info.log
</property>
<!--
%T - Time (15:04:05 MST)
%t - Time (15:04)
%D - Date (2006/01/02)
%d - Date (01/02/06)
%L - Level (FNST, FINE, DEBG, TRAC, WARN, EROR, CRIT)
%S - Source
%M - Message
It ignores unknown format strings (and removes them)
Recommended: "[%D %T] [%L] (%S) %M"
-->
<property
name=
"format"
>
[%D %T] [%L] [%S] %M
</property>
<property
name=
"rotate"
>
true
</property>
<!-- true enables log rotation, otherwise append -->
<property
name=
"maxsize"
>
0M
</property>
<!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property
name=
"maxlines"
>
0K
</property>
<!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property
name=
"daily"
>
true
</property>
<!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter
enabled=
"true"
>
<tag>
warn_file
</tag>
<type>
file
</type>
<level>
WARNING
</level>
<property
name=
"filename"
>
logs/warn.log
</property>
<property
name=
"format"
>
[%D %T] [%L] [%S] %M
</property>
<property
name=
"rotate"
>
true
</property>
<!-- true enables log rotation, otherwise append -->
<property
name=
"maxsize"
>
0M
</property>
<!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property
name=
"maxlines"
>
0K
</property>
<!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property
name=
"daily"
>
true
</property>
<!-- Automatically rotates when a log message is written after midnight -->
</filter>
<filter
enabled=
"true"
>
<tag>
error_file
</tag>
<type>
file
</type>
<level>
ERROR
</level>
<property
name=
"filename"
>
logs/error.log
</property>
<property
name=
"format"
>
[%D %T] [%L] [%S] %M
</property>
<property
name=
"rotate"
>
true
</property>
<!-- true enables log rotation, otherwise append -->
<property
name=
"maxsize"
>
0M
</property>
<!-- \d+[KMG]? Suffixes are in terms of 2**10 -->
<property
name=
"maxlines"
>
0K
</property>
<!-- \d+[KMG]? Suffixes are in terms of thousands -->
<property
name=
"daily"
>
true
</property>
<!-- Automatically rotates when a log message is written after midnight -->
</filter>
</logging>
echo/wss-echo/change_log.md
View file @
bfb3fc6a
# ws-echo #
# ws
s
-echo #
---
---
*getty websocket code examples of Echo Example*
*getty
secure
websocket code examples of Echo Example*
## LICENSE ##
## LICENSE ##
---
---
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment