Apply .gitignore rules
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
package fileUtil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"goutil/timeUtil"
|
||||
)
|
||||
|
||||
// 大文件对象,可用于连续写入内容而不关闭文件,直到达到指定的大小
|
||||
type BigFile struct {
|
||||
// 文件夹名称
|
||||
path string
|
||||
|
||||
// 当前文件名称
|
||||
fileName string
|
||||
|
||||
// 文件名称前缀
|
||||
fileNamePrefix string
|
||||
|
||||
// 当前文件大小(单位:Byte)
|
||||
fileSize int
|
||||
|
||||
// 最大的文件大小(单位:Byte)
|
||||
maxFileSize int
|
||||
|
||||
// 文件对象
|
||||
file *os.File
|
||||
|
||||
// 获得新文件名称的方法
|
||||
newFileNameFunc func(string, string) string
|
||||
}
|
||||
|
||||
// 获取文件的完整路径
|
||||
func (this *BigFile) getFullPath() string {
|
||||
return filepath.Join(this.path, this.fileName)
|
||||
}
|
||||
|
||||
// 初始化文件对象
|
||||
func (this *BigFile) initFile() error {
|
||||
// 初始化文件名称
|
||||
this.fileName = this.newFileNameFunc(this.fileNamePrefix, this.fileName)
|
||||
|
||||
// 初始化文件大小
|
||||
this.fileSize = 0
|
||||
|
||||
// 打开文件
|
||||
file, err := os.OpenFile(this.getFullPath(), os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm|os.ModeTemporary)
|
||||
if err != nil {
|
||||
return fmt.Errorf("打开文件%s错误,错误信息为:%s", this.getFullPath(), err)
|
||||
} else {
|
||||
this.file = file
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 返回当前文件名称
|
||||
// 返回值:
|
||||
// 当前文件名称
|
||||
func (this *BigFile) FileName() string {
|
||||
return this.fileName
|
||||
}
|
||||
|
||||
// 保存消息
|
||||
// message:消息内容
|
||||
// 返回值:错误对象
|
||||
func (this *BigFile) SaveMessage(message string) error {
|
||||
if this.file == nil {
|
||||
return fmt.Errorf("文件对象为空,path:%s", this.getFullPath())
|
||||
}
|
||||
|
||||
// 增加文件大小
|
||||
this.fileSize += len([]byte(message))
|
||||
|
||||
// 写入消息(在结尾处增加一个换行符\n)
|
||||
message = fmt.Sprintf("%s\n", message)
|
||||
if _, err := this.file.WriteString(message); err != nil {
|
||||
return fmt.Errorf("向文件%s写入信息错误,错误信息为:%s", this.getFullPath(), err)
|
||||
}
|
||||
|
||||
// 如果达到了文件的上限,则关闭文件并重新打开一个新文件
|
||||
if this.fileSize >= this.maxFileSize {
|
||||
this.Close()
|
||||
this.initFile()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 写入字节消息
|
||||
// message:消息内容
|
||||
// 返回值:错误对象
|
||||
func (this *BigFile) WriteMessage(message []byte) error {
|
||||
if this.file == nil {
|
||||
return fmt.Errorf("文件对象为空,path:%s", this.getFullPath())
|
||||
}
|
||||
|
||||
// 增加文件大小
|
||||
this.fileSize += len(message)
|
||||
|
||||
// 写入消息
|
||||
if _, err := this.file.Write(message); err != nil {
|
||||
return fmt.Errorf("向文件%s写入信息错误,错误信息为:%s", this.getFullPath(), err)
|
||||
}
|
||||
|
||||
// 如果达到了文件的上限,则关闭文件并重新打开一个新文件
|
||||
if this.fileSize >= this.maxFileSize {
|
||||
this.Close()
|
||||
this.initFile()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 关闭对象
|
||||
// 返回值:无
|
||||
func (this *BigFile) Close() {
|
||||
if this.file != nil {
|
||||
this.file.Close()
|
||||
this.file = nil
|
||||
}
|
||||
}
|
||||
|
||||
// 创建新的大文件对象(obsolete)
|
||||
// _path:文件夹路径
|
||||
// _maxFileSize:单个文件大小的最大值(单位:Byte)
|
||||
// 返回值:
|
||||
// 大文件对象
|
||||
// 错误对象
|
||||
func NewBigFile(_path string, _maxFileSize int) (*BigFile, error) {
|
||||
return NewBigFileWithNewFileNameFunc(_path, "default", _maxFileSize, newFileName)
|
||||
}
|
||||
|
||||
// 创建新的大文件对象
|
||||
// _path:文件夹路径
|
||||
// _fileNamePrefix:文件名称前缀
|
||||
// _maxFileSize:单个文件大小的最大值(单位:Byte)
|
||||
// 返回值:
|
||||
// 大文件对象
|
||||
// 错误对象
|
||||
func NewBigFile2(_path, _fileNamePrefix string, _maxFileSize int) (*BigFile, error) {
|
||||
return NewBigFileWithNewFileNameFunc(_path, _fileNamePrefix, _maxFileSize, newFileName)
|
||||
}
|
||||
|
||||
// 创建新的大文件对象
|
||||
// _path:文件夹路径
|
||||
// _fileNamePrefix:文件名称前缀
|
||||
// _maxFileSize:单个文件大小的最大值(单位:Byte)
|
||||
// _newFileNameFunc:创建新文件名称的方法
|
||||
// 返回值:
|
||||
// 大文件对象
|
||||
// 错误对象
|
||||
func NewBigFileWithNewFileNameFunc(_path, _fileNamePrefix string, _maxFileSize int, _newFileNameFunc func(string, string) string) (*BigFile, error) {
|
||||
return NewBigFileWithNewFileNameFunc2(_path, _fileNamePrefix, "default", _maxFileSize, _newFileNameFunc)
|
||||
}
|
||||
|
||||
// 创建新的大文件对象
|
||||
// _path:文件夹路径
|
||||
// _fileNamePrefix:文件名称前缀
|
||||
// _fileName:文件名称
|
||||
// _maxFileSize:单个文件大小的最大值(单位:Byte)
|
||||
// _newFileNameFunc:创建新文件名称的方法
|
||||
// 返回值:
|
||||
// 大文件对象
|
||||
// 错误对象
|
||||
func NewBigFileWithNewFileNameFunc2(_path, _fileNamePrefix, _fileName string, _maxFileSize int, _newFileNameFunc func(string, string) string) (*BigFile, error) {
|
||||
// 判断文件夹是否存在,如果不存在则创建
|
||||
if !IsDirExists(_path) {
|
||||
os.MkdirAll(_path, os.ModePerm|os.ModeTemporary)
|
||||
}
|
||||
|
||||
// 初始化对象
|
||||
obj := &BigFile{
|
||||
path: _path,
|
||||
fileNamePrefix: _fileNamePrefix,
|
||||
fileName: _fileName,
|
||||
maxFileSize: _maxFileSize,
|
||||
newFileNameFunc: _newFileNameFunc,
|
||||
}
|
||||
|
||||
// 初始化文件对象
|
||||
if err := obj.initFile(); err != nil {
|
||||
obj.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
// 创建新的文件名称
|
||||
// prefix:前缀
|
||||
// currFileName:当前文件名称
|
||||
// 返回值:
|
||||
// 新的文件名称
|
||||
func newFileName(prefix, currFileName string) string {
|
||||
return fmt.Sprintf("%s_%s.data", prefix, timeUtil.Format(time.Now(), "yyyyMMddHHmmss"))
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/*
|
||||
zlib压缩、解压缩相关的助手包
|
||||
*/
|
||||
package zlibUtil
|
||||
@@ -0,0 +1,374 @@
|
||||
package webServer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"goutil/logUtil"
|
||||
"goutil/netUtil"
|
||||
"goutil/typeUtil"
|
||||
"goutil/zlibUtil"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultMaxMemory = 32 << 20 // 32 MB
|
||||
)
|
||||
|
||||
// 请求上下文对象
|
||||
type Context struct {
|
||||
// 用户自定义数据(注册回调时设置,通过Context传到用户回调) Add:raojianhua Time:2022-02-16 17:00
|
||||
userData interface{}
|
||||
|
||||
// 请求对象
|
||||
request *http.Request
|
||||
|
||||
// 响应对象
|
||||
responseWriter http.ResponseWriter
|
||||
|
||||
// 数据是否已经解析数据
|
||||
ifBodyParsed bool
|
||||
|
||||
// 请求数据
|
||||
bodyContent []byte
|
||||
|
||||
// Form的数据是否已经解析
|
||||
ifFormParsed bool
|
||||
|
||||
// MultipleForm的数据是否已经解析
|
||||
ifMultipartFormParsed bool
|
||||
|
||||
// 是否经过了负载均衡的中转,如果是,则需要通过header获取客户端实际的请求地址
|
||||
ifDelegate bool
|
||||
|
||||
// 请求的开始时间
|
||||
StartTime time.Time
|
||||
|
||||
// 请求的结束时间
|
||||
EndTime time.Time
|
||||
|
||||
// 处理请求数据的处理器(例如压缩、解密等)
|
||||
requestDataHandler func(*Context, []byte) ([]byte, error)
|
||||
|
||||
// 处理响应数据的处理器(例如压缩、加密等)
|
||||
responseDataHandler func(*Context, []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
// 获取用户自定义数据(注册回调时设置,通过Context传到用户回调) Add:raojianhua Time:2022-02-16 17:00
|
||||
func (this *Context) GetUserData() interface{} {
|
||||
return this.userData
|
||||
}
|
||||
|
||||
// 获取请求对象
|
||||
func (this *Context) GetRequest() *http.Request {
|
||||
return this.request
|
||||
}
|
||||
|
||||
// 获取响应对象
|
||||
func (this *Context) GetResponseWriter() http.ResponseWriter {
|
||||
return this.responseWriter
|
||||
}
|
||||
|
||||
// 获取请求路径(不带参数)
|
||||
func (this *Context) GetRequestPath() string {
|
||||
return this.request.URL.Path
|
||||
}
|
||||
|
||||
// 获取请求的客户端的IP地址
|
||||
func (this *Context) GetRequestIP() string {
|
||||
if this.ifDelegate {
|
||||
return netUtil.GetHttpAddr2(this.request).Host
|
||||
}
|
||||
|
||||
return netUtil.GetHttpAddr(this.request).Host
|
||||
}
|
||||
|
||||
// 获取请求执行的秒数
|
||||
func (this *Context) GetExecuteSeconds() int64 {
|
||||
return this.EndTime.Unix() - this.StartTime.Unix()
|
||||
}
|
||||
|
||||
// 格式化context对象
|
||||
func (this *Context) String() string {
|
||||
var bodyContent string
|
||||
if bytes, exist, err := this.GetRequestBytes(); err == nil && exist {
|
||||
bodyContent = string(bytes)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("IP:%s, URL:%s, FormValue:%#v, BodyContent:%s",
|
||||
this.GetRequestIP(), this.GetRequestPath(), this.GetFormValueData(), bodyContent)
|
||||
}
|
||||
|
||||
func (this *Context) parseForm() {
|
||||
if !this.ifFormParsed {
|
||||
// 先保存一份body
|
||||
this.parseBodyContent()
|
||||
|
||||
this.request.ParseMultipartForm(32 << 20)
|
||||
this.ifFormParsed = true
|
||||
}
|
||||
}
|
||||
|
||||
// 获取请求的参数值(包括GET/POST/PUT/DELETE等所有参数)
|
||||
func (this *Context) FormValue(key string) (value string) {
|
||||
this.parseForm()
|
||||
|
||||
return this.request.FormValue(key)
|
||||
}
|
||||
|
||||
// 获取POST的参数值
|
||||
func (this *Context) PostFormValue(key string) (value string) {
|
||||
this.parseForm()
|
||||
|
||||
return this.request.PostFormValue(key)
|
||||
}
|
||||
|
||||
// 获取所有参数的MapData类型(包括GET/POST/PUT/DELETE等所有参数)
|
||||
func (this *Context) GetFormValueData() typeUtil.MapData {
|
||||
this.parseForm()
|
||||
|
||||
valueMap := make(map[string]interface{})
|
||||
for k, v := range this.request.Form {
|
||||
valueMap[k] = v[0]
|
||||
}
|
||||
|
||||
return typeUtil.MapData(valueMap)
|
||||
}
|
||||
|
||||
// 获取POST参数的MapData类型
|
||||
func (this *Context) GetPostFormValueData() typeUtil.MapData {
|
||||
this.parseForm()
|
||||
|
||||
valueMap := make(map[string]interface{})
|
||||
for k, v := range this.request.PostForm {
|
||||
valueMap[k] = v[0]
|
||||
}
|
||||
|
||||
return typeUtil.MapData(valueMap)
|
||||
}
|
||||
|
||||
func (this *Context) parseMultipartForm() {
|
||||
if !this.ifMultipartFormParsed {
|
||||
this.request.ParseMultipartForm(defaultMaxMemory)
|
||||
this.ifMultipartFormParsed = true
|
||||
}
|
||||
}
|
||||
|
||||
// 获取MultipartForm的MapData类型
|
||||
func (this *Context) GetMultipartFormValueData() typeUtil.MapData {
|
||||
this.parseMultipartForm()
|
||||
|
||||
valueMap := make(map[string]interface{})
|
||||
if this.request.MultipartForm != nil {
|
||||
for k, v := range this.request.MultipartForm.Value {
|
||||
valueMap[k] = v[0]
|
||||
}
|
||||
}
|
||||
|
||||
return typeUtil.MapData(valueMap)
|
||||
}
|
||||
|
||||
func (this *Context) parseBodyContent() (err error) {
|
||||
if this.ifBodyParsed {
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
this.request.Body.Close()
|
||||
this.ifBodyParsed = true
|
||||
|
||||
if len(this.bodyContent) > 0 {
|
||||
this.request.Body = ioutil.NopCloser(bytes.NewBuffer(this.bodyContent))
|
||||
}
|
||||
}()
|
||||
|
||||
this.bodyContent, err = ioutil.ReadAll(this.request.Body)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("url:%s,read body failed. Err:%s", this.GetRequestPath(), err))
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获取请求字节数据
|
||||
// 返回值:
|
||||
// []byte:请求字节数组
|
||||
// exist:是否存在数据
|
||||
// error:错误信息
|
||||
func (this *Context) GetRequestBytes() (result []byte, exist bool, err error) {
|
||||
if err = this.parseBodyContent(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
result = this.bodyContent
|
||||
if result == nil || len(result) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// handle request data
|
||||
if this.requestDataHandler != nil {
|
||||
if result, err = this.requestDataHandler(this, result); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
exist = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获取请求字符串数据
|
||||
// 返回值:
|
||||
// result:请求字符串数据
|
||||
// exist:是否存在数据
|
||||
// error:错误信息
|
||||
func (this *Context) GetRequestString() (result string, exist bool, err error) {
|
||||
var data []byte
|
||||
if data, exist, err = this.GetRequestBytes(); err != nil || !exist {
|
||||
return
|
||||
}
|
||||
|
||||
result = string(data)
|
||||
exist = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 反序列化为对象(JSON)
|
||||
// obj:反序列化结果数据
|
||||
// isCompressed:数据是否已经被压缩
|
||||
// 返回值:
|
||||
// 错误对象
|
||||
func (this *Context) Unmarshal(obj interface{}) (exist bool, err error) {
|
||||
var data []byte
|
||||
if data, exist, err = this.GetRequestBytes(); err != nil || !exist {
|
||||
return
|
||||
}
|
||||
|
||||
// Unmarshal
|
||||
if err = json.Unmarshal(data, &obj); err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("Unmarshal %s failed. Err::%s", string(data), err))
|
||||
return
|
||||
}
|
||||
|
||||
exist = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 反序列化为对象(zlib+JSON)
|
||||
// obj:反序列化结果数据
|
||||
// isCompressed:数据是否已经被压缩
|
||||
// 返回值:
|
||||
// 错误对象
|
||||
func (this *Context) UnmarshalZlib(obj interface{}) (exist bool, err error) {
|
||||
var data []byte
|
||||
if data, exist, err = this.GetRequestBytes(); err != nil || !exist {
|
||||
return
|
||||
}
|
||||
|
||||
zlibBytes, err := zlibUtil.Decompress(data)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("Decompress %v failed. Err::%s", string(data), err))
|
||||
return
|
||||
}
|
||||
|
||||
// Unmarshal
|
||||
if err = json.Unmarshal(zlibBytes, &obj); err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("Unmarshal %s failed. Err::%s", string(data), err))
|
||||
return
|
||||
}
|
||||
|
||||
exist = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (this *Context) writeBytes(data []byte) error {
|
||||
var err error
|
||||
if this.responseDataHandler != nil {
|
||||
if data, err = this.responseDataHandler(this, data); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = this.responseWriter.Write(data)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 输出字符串给客户端
|
||||
func (this *Context) WriteString(result string) error {
|
||||
return this.writeBytes([]byte(result))
|
||||
}
|
||||
|
||||
// 输出json数据给客户端
|
||||
func (this *Context) WriteJson(result interface{}) error {
|
||||
data, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("Marshal %v failed. Err::%s", result, err))
|
||||
return err
|
||||
}
|
||||
|
||||
return this.writeBytes(data)
|
||||
}
|
||||
|
||||
// 输出zlib+json数据给客户端
|
||||
func (this *Context) WriteZlibJson(result interface{}) error {
|
||||
data, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("Marshal %v failed. Err::%s", result, err))
|
||||
return err
|
||||
}
|
||||
|
||||
zlibBytes, err := zlibUtil.Compress(data, zlib.DefaultCompression)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("Compress %v failed. Err::%s", string(data), err))
|
||||
return err
|
||||
}
|
||||
|
||||
return this.writeBytes(zlibBytes)
|
||||
}
|
||||
|
||||
/*
|
||||
Http状态码301和302概念简单区别
|
||||
302重定向表示临时性转移(Temporarily Moved ),当一个网页URL需要短期变化时使用。 301重定向是永久的重定向,搜索引擎在抓取新内容的同时也将旧的网址替换为重定向之后的网址。 302重定向是临时的重定向,搜索引擎会抓取新的内容而保留旧的网址。
|
||||
如果是短链,需要每次都访问原来的短链地址,以便于进行统计,则使用302重定向
|
||||
*/
|
||||
// 重定向到其它页面(301)
|
||||
func (this *Context) RedirectTo(url string) {
|
||||
this.responseWriter.Header().Set("Location", url)
|
||||
this.responseWriter.WriteHeader(301)
|
||||
}
|
||||
|
||||
// 重定向到其它页面(302)
|
||||
func (this *Context) RedirectTo302(url string) {
|
||||
this.responseWriter.Header().Set("Location", url)
|
||||
this.responseWriter.WriteHeader(302)
|
||||
}
|
||||
|
||||
// 新建API上下文对象
|
||||
// request:请求对象
|
||||
// responseWriter:应答写对象
|
||||
// _ifDelegate:是否经过负载均衡
|
||||
// 返回值:
|
||||
// *Context:上下文
|
||||
func newContext(request *http.Request, responseWriter http.ResponseWriter,
|
||||
requestDataHandler func(*Context, []byte) ([]byte, error),
|
||||
responseDataHandler func(*Context, []byte) ([]byte, error),
|
||||
_ifDelegate bool) *Context {
|
||||
return &Context{
|
||||
request: request,
|
||||
responseWriter: responseWriter,
|
||||
StartTime: time.Now(),
|
||||
EndTime: time.Now(),
|
||||
requestDataHandler: requestDataHandler,
|
||||
responseDataHandler: responseDataHandler,
|
||||
ifDelegate: _ifDelegate,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package websocketServer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gorilla/websocket"
|
||||
"net/http"
|
||||
webServer "Framework/webServer"
|
||||
"strconv"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 处理HTTP请求
|
||||
func httpHandler(cxt *webServer.Context) {
|
||||
msg := "test msg"
|
||||
cxt.GetResponseWriter().Write([]byte(msg))
|
||||
}
|
||||
|
||||
// websocket连接事件
|
||||
func onConnFunc(ctx *Context) {
|
||||
fmt.Printf("new conn, ip: %s %p\n", ctx.GetWebServerContext().GetRequestIP(), ctx)
|
||||
ctx.SendMessage(websocket.TextMessage, []byte("Hello")) // 返回数据
|
||||
}
|
||||
|
||||
// websocket关闭事件
|
||||
func onCloseFunc(ctx *Context) {
|
||||
fmt.Printf("close conn, ip: %s %p\n", ctx.GetWebServerContext().GetRequestIP(), ctx)
|
||||
}
|
||||
|
||||
// websocket接收事件
|
||||
func onMsgFunc(ctx *Context, msgType int, msgData []byte) {
|
||||
fmt.Printf("%p ", ctx)
|
||||
fmt.Println("msg ip:", ctx.GetWebServerContext().GetRequestIP(), "msg type:", msgType, "msg:", string(msgData))
|
||||
ctx.SendMessage(msgType, []byte("SVR: "+string(msgData))) // 返回数据
|
||||
|
||||
// 主动关闭连接测试
|
||||
if string(msgData) == "close" {
|
||||
ctx.SendMessage(msgType, []byte("close")) // 返回数据
|
||||
//time.Sleep(time.Microsecond * 100)
|
||||
ctx.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func TestWsServer(t *testing.T) {
|
||||
var ssl bool = false
|
||||
var server IServer
|
||||
if ssl {
|
||||
server = NewWssServer(":22222", "cert.pem", "key.pem", false)
|
||||
} else {
|
||||
server = NewWsServer(":22222", false)
|
||||
}
|
||||
|
||||
server.SetIfDelegate(false)
|
||||
|
||||
// 注册HTTP处理函数
|
||||
server.RegisterHandler("/http", httpHandler, &webServer.HandlerConfig{})
|
||||
|
||||
// 设置websocket允许跨域访问
|
||||
server.GetUpgrader().CheckOrigin = func(r *http.Request) bool {
|
||||
return true
|
||||
}
|
||||
//upgrader := &websocket.Upgrader{
|
||||
// // 允许跨域
|
||||
// CheckOrigin: func(r *http.Request) bool {
|
||||
// return true
|
||||
// },
|
||||
//}
|
||||
//server.SetUpgrader(upgrader)
|
||||
|
||||
// 注册websocket处理事件
|
||||
server.RegisterWebsocketHandler("/websocket", &EventCallbackFuncs{
|
||||
OnConnFunc: onConnFunc,
|
||||
OnCloseFunc: onCloseFunc,
|
||||
OnMsgFunc: onMsgFunc,
|
||||
}, &webServer.HandlerConfig{})
|
||||
|
||||
// 设置广播并发数
|
||||
server.SetBroadcastConcurrent(2)
|
||||
|
||||
// 设置接收到Ping消息时,自动回复Pong信息
|
||||
server.SetAutoPong(true)
|
||||
|
||||
// 设置心跳检测信息(心跳检测周期10秒;缺少2个心跳周期断开连接)
|
||||
server.SetHeartbeatDetectInfo(2, time.Second*10)
|
||||
|
||||
// 广播测试
|
||||
go func() {
|
||||
var i = 0
|
||||
for {
|
||||
time.Sleep(time.Second * 10)
|
||||
// 广播测试
|
||||
server.BroadcastMessage(websocket.TextMessage, []byte(strconv.Itoa(i)))
|
||||
i++
|
||||
}
|
||||
}()
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
server.Start(&wg)
|
||||
}
|
||||
Reference in New Issue
Block a user