当前位置: 首页 > news >正文

关于做ppt的网站vps 用ip可以访问网站么

关于做ppt的网站,vps 用ip可以访问网站么,哈尔滨一恒建设,新手学做网站代码用 Go 编写一个简单的 WebSocket 推送服务 本文中代码可以在 github.com/alfred-zhon… 获取。 背景 最近拿到需求要在网页上展示报警信息。以往报警信息都是通过短信#xff0c;微信和 App 推送给用户的#xff0c;现在要让登录用户在网页端也能实时接收到报警推送。 依稀记…用 Go 编写一个简单的 WebSocket 推送服务 本文中代码可以在 github.com/alfred-zhon… 获取。 背景 最近拿到需求要在网页上展示报警信息。以往报警信息都是通过短信微信和 App 推送给用户的现在要让登录用户在网页端也能实时接收到报警推送。 依稀记得以前工作的时候遇到过类似的需求。因为以前的浏览器标准比较陈旧并且那时用 Java 较多所以那时候解决这个问题就用了 Comet4J。具体的原理就是长轮询长链接。但现在毕竟 html5 流行开来了IE 都被 Edge 接替了再用以前这种技术就显得过时。 很早以前就听过 WebSocket 的大名但因为那时很多用户的浏览器还不支持所以对这个技术也就是浅尝辄止没有太深入研究过。现在趁着项目需要就来稍微深入了解一下。 websocket 简介 以往浏览器要获取服务端数据都是通过发送 HTTP 请求然后等待服务端回应的。也就是说浏览器端一直是整个请求的发起者只有它主动才能获取到数据。而要让浏览器一侧能够获取到服务端的实时数据就需要不停地向服务端发起请求。虽然大多数情况下并没有获取到实际数据但这大大增加了网络压力对于服务端来说压力也直线上升。 后来我们学会了使用长连接 长轮询的方式。换句话说也就是延长 HTTP 请求的存在时间尽量保持 HTTP 连接。虽然这在一定程度上降低了不少压力但仍然需要不停地进行轮询也做不到真正的实时性。借用一张图 随着 HTML5 的到来WebSocket 在 2011 年被定为标准详情请参见 RFC 6455。 借用 《Go Web 编程》的话。WebSocket 采用了一些特殊的报头使得浏览器和服务器只需要做一个握手的动作就可以在浏览器和服务器之间建立一条连接通道。且此连接会保持在活动状态你可以使用 JavaScript 来向连接写入或从中接收数据就像在使用一个常规的 TCP Socket 一样。它解决了 Web 实时化的问题。 由于 WebSocket 是全双工通信所以当建立了 WebSocket 连接之后接下来的通信就类似于传统的 TCP 通信了。客户端和服务端可以相互发送数据不再有实时性的问题。 开发包的选择 在 Go 官方的 SDK 中并不包含对 WebSocket 的支持所以必须使用第三方库。 要使用 Golang 开发 WebSocket选择基本就在 x/net/websocket 和 gorilla/websocket 之间。《Go Web 编程》一书中的例子使用了 x/net/websocket 作为开发包而且貌似它也更加官方且正式。而实际根据我在网上查询得到的反馈看来并非如此。x/net/websocket 貌似 Bug 较多且较为不稳定问题解决也并不及时。相比之下gorilla/websocket 则更加优秀。 还有对于 Gorilla web toolkit 组织的贡献必须予以感谢。?。其下不仅有 WebSocket 的实现也有一些其他工具。欢迎大家使用并且能够给予反馈或贡献。 推送服务实现 基本原理 项目初步设计如下 server 启动以后会注册两个 Handler。 websocketHandler 用于提供浏览器端发送 Upgrade 请求并升级为 WebSocket 连接。pushHandler 用于提供外部推送端发送推送数据的请求。浏览器首先连接 websocketHandler 默认地址为 ws://ip:port/ws升级请求为 WebSocket 连接当连接建立之后需要发送注册信息进行注册。这里注册信息中包含一个 token 信息。server 会对提供的 token 进行验证并获取到相应的 userId通常来说一个 userId 可能同时关联许多 token并保存维护好 token, userId 和 conn连接之间的关系。 推送端发送推送数据的请求到 pushHandler默认地址为 ws://ip:port/push请求中包含了 userId 字段和 message 字段。server 会根据 userId 获取到所有此时连接到该 server 的 conn然后将 message 一一进行推送。 由于推送服务的实时性推送的数据并没有也不需要进行缓存。 代码详解 我在此处会稍微讲述一下代码的基本构成也顺便说说 Go 语言中一些常用的写法和模式本人也是从其他语言转向 Go 语言毕竟 Go 语言也相当年轻。所以有建议的话敬请提出。。由于 Go 语言的发明人和一些主要维护者大都来自于 C/C 语言所以 Go 语言的代码也更偏向于 C/C 系。 首先先看一下 Server 的结构 // Server defines parameters for running websocket server. type Server struct {// Address for server to listen onAddr string// Path for websocket request, default /ws.WSPath string// Path for push message, default /push.PushPath string// Upgrader is for upgrade connection to websocket connection using// github.com/gorilla/websocket.//// If Upgrader is nil, default upgrader will be used. Default upgrader is// set ReadBufferSize and WriteBufferSize to 1024, and CheckOrigin always// returns true.Upgrader *websocket.Upgrader// Check token if its valid and return userID. If token is valid, userID// must be returned and ok should be true. Otherwise ok should be false.AuthToken func(token string) (userID string, ok bool)// Authorize push request. Message will be sent if it returns true,// otherwise the request will be discarded. Default nil and push request// will always be accepted.PushAuth func(r *http.Request) boolwh *websocketHandlerph *pushHandler } 复制代码 PS: 由于我整个项目的注释都是用英文写的所以见谅了希望不妨碍阅读。 这里说一下 Upgrader *websocket.Upgrader这是 gorilla/websocket 包的对象它用来升级 HTTP 请求。 如果一个结构体参数过多通常不建议直接初始化而是使用它提供的 New 方法。这里是 // NewServer creates a new Server. func NewServer(addr string) *Server {return Server{Addr: addr,WSPath: serverDefaultWSPath,PushPath: serverDefaultPushPath,} } 复制代码这也是 Go 语言对外提供初始化方法的一种常见用法。 然后 Server 使用 ListenAndServe 方法启动并监听端口与 http 包的使用类似 // ListenAndServe listens on the TCP network address and handle websocket // request. func (s *Server) ListenAndServe() error {b : binder{userID2EventConnMap: make(map[string]*[]eventConn),connID2UserIDMap: make(map[string]string),}// websocket request handlerwh : websocketHandler{upgrader: defaultUpgrader,binder: b,}if s.Upgrader ! nil {wh.upgrader s.Upgrader}if s.AuthToken ! nil {wh.calcUserIDFunc s.AuthToken}s.wh whhttp.Handle(s.WSPath, s.wh)// push request handlerph : pushHandler{binder: b,}if s.PushAuth ! nil {ph.authFunc s.PushAuth}s.ph phhttp.Handle(s.PushPath, s.ph)return http.ListenAndServe(s.Addr, nil) } 复制代码这里我们生成了两个 Handler分别为 websocketHandler 和 pushHandler。websocketHandler 负责与浏览器建立连接并传输数据而 pushHandler 则处理推送端的请求。可以看到这里两个 Handler 都封装了一个 binder 对象。这个 binder 用于维护 token - userID - Conn 的关系 // binder is defined to store the relation of userID and eventConn type binder struct {mu sync.RWMutex// map stores key: userID and value of related slice of eventConnuserID2EventConnMap map[string]*[]eventConn// map stores key: connID and value: userIDconnID2UserIDMap map[string]string } 复制代码websocketHandler 具体看一下 websocketHandler 的实现。 // websocketHandler defines to handle websocket upgrade request. type websocketHandler struct {// upgrader is used to upgrade request.upgrader *websocket.Upgrader// binder stores relations about websocket connection and userID.binder *binder// calcUserIDFunc defines to calculate userID by token. The userID will// be equal to token if this function is nil.calcUserIDFunc func(token string) (userID string, ok bool) } 复制代码很简单的结构。websocketHandler 实现了 http.Handler 接口 // First try to upgrade connection to websocket. If success, connection will // be kept until client send close message or server drop them. func (wh *websocketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {wsConn, err : wh.upgrader.Upgrade(w, r, nil)if err ! nil {return}defer wsConn.Close()// handle Websocket requestconn : NewConn(wsConn)conn.AfterReadFunc func(messageType int, r io.Reader) {var rm RegisterMessagedecoder : json.NewDecoder(r)if err : decoder.Decode(rm); err ! nil {return}// calculate userID by tokenuserID : rm.Tokenif wh.calcUserIDFunc ! nil {uID, ok : wh.calcUserIDFunc(rm.Token)if !ok {return}userID uID}// bindwh.binder.Bind(userID, rm.Event, conn)}conn.BeforeCloseFunc func() {// unbindwh.binder.Unbind(conn)}conn.Listen() } 复制代码首先将传入的 http.Request 转换为 websocket.Conn再将其分装为我们自定义的一个 wserver.Conn封装或者说是组合是 Go 语言的典型用法。记住Go 语言没有继承只有组合。然后设置了 Conn 的 AfterReadFunc 和 BeforeCloseFunc 方法接着启动了 conn.Listen()。AfterReadFunc 意思是当 Conn 读取到数据后尝试验证并根据 token 计算 userID然乎 bind 注册绑定。BeforeCloseFunc 则为 Conn 关闭前进行解绑操作。 pushHandler pushHandler 则容易理解。它解析请求然后推送数据 // Authorize if needed. Then decode the request and push message to each // realted websocket connection. func (s *pushHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {if r.Method ! http.MethodPost {w.WriteHeader(http.StatusMethodNotAllowed)return}// authorizeif s.authFunc ! nil {if ok : s.authFunc(r); !ok {w.WriteHeader(http.StatusUnauthorized)return}}// read requestvar pm PushMessagedecoder : json.NewDecoder(r.Body)if err : decoder.Decode(pm); err ! nil {w.WriteHeader(http.StatusBadRequest)w.Write([]byte(ErrRequestIllegal.Error()))return}// validate the dataif pm.UserID || pm.Event || pm.Message {w.WriteHeader(http.StatusBadRequest)w.Write([]byte(ErrRequestIllegal.Error()))return}cnt, err : s.push(pm.UserID, pm.Event, pm.Message)if err ! nil {w.WriteHeader(http.StatusInternalServerError)w.Write([]byte(err.Error()))return}result : strings.NewReader(fmt.Sprintf(message sent to %d clients, cnt))io.Copy(w, result) } 复制代码Conn Conn (此处指 wserver.Conn) 为 websocket.Conn 的包装。 // Conn wraps websocket.Conn with Conn. It defines to listen and read // data from Conn. type Conn struct {Conn *websocket.ConnAfterReadFunc func(messageType int, r io.Reader)BeforeCloseFunc func()once sync.Onceid stringstopCh chan struct{} } 复制代码最主要的方法为 Listen() // Listen listens for receive data from websocket connection. It blocks // until websocket connection is closed. func (c *Conn) Listen() {c.Conn.SetCloseHandler(func(code int, text string) error {if c.BeforeCloseFunc ! nil {c.BeforeCloseFunc()}if err : c.Close(); err ! nil {log.Println(err)}message : websocket.FormatCloseMessage(code, )c.Conn.WriteControl(websocket.CloseMessage, message, time.Now().Add(time.Second))return nil})// Keeps reading from Conn util get error. ReadLoop:for {select {case -c.stopCh:break ReadLoopdefault:messageType, r, err : c.Conn.NextReader()if err ! nil {// TODO: handle read error maybebreak ReadLoop}if c.AfterReadFunc ! nil {c.AfterReadFunc(messageType, r)}}} } 复制代码主要设置了当 websocket 连接关闭时的处理和不停地读取数据。 文中很难全面地描述整个代码的运作流程像具体阅读代码请前往 github.com/alfred-zhon… 获取。 后记 代码我已经进行了一定的测试也已经在正式环境中运行了一段时间。但是代码可能仍然不够稳定所以在使用过程中出现问题也实属正常。随意随时欢迎大家给我提 issues 或者 PRs。 参考 《Go Web 编程》 --- astaxieWeb 通信 之 长连接、长轮询long polling --- hoojoGorilla web toolkit
http://wiki.neutronadmin.com/news/260727/

相关文章:

  • 网站开发技术选型经营网站挣钱
  • 网站推广排名公司wordpress mp3播放器
  • 上海做网站的公司联系方式上海做网站建设公司
  • 代做课件的网站包装设计灵感网站
  • 学校网站建设情况说明书wordpress 表单
  • 建网站公司用什么网站程序昆明企业网站排名公司
  • app网站与普通网站的区别网站备案怎么转入
  • php网站开发工程师招聘会开启wordpress多站点
  • 网站底部友情链接怎么做的wordpress菜单没有了
  • 工业设计网站排名网站建设做的人多吗
  • wordpress 经典网站设计师培训感悟
  • 延安做网站的公司seo培训机构
  • ftp制作网站深圳品牌网站建设公司
  • 网站建设网络推广公司百度wordpress安装
  • 软件下载网站制作介绍自己做的网站的论文
  • 临沂手机网站制作房地产市场规模
  • 网站适配手机屏幕万网买好域名后如何开通网站
  • 合肥建站推广网站建设需要哪些人才
  • 12306网站学生做单页面优化的重点
  • 网站建设相关资质网站域名空间地址
  • 单屏网站设计做网站办贷款
  • 网站上线准备工作wordpress月亮
  • 装修网站建设公司电商设备网站怎么做
  • 南京汤山建设银行网站WordPress rss连接
  • 莱芜招聘网百度seo优化方法
  • 网站开发充值功能Wordpress html5 动画
  • 扬州网站建设icp备商城类网站建设
  • 手机网站弹出导航菜单手机网站模板 餐饮
  • 做网站设计工资多少钱wordpress归档页面
  • 中国建设工程机械网站东莞网站优化一般多少钱