`

go语言五——http模块实现个状态计数器

 
阅读更多

实现一个简易的“状态机”

server # go run server.go
2013/06/06 14:10:11 counterB timedout
 //超时10秒总和未达到10

client # go run client.go counterA 1
Continue
client # go run client.go counterA 3
Continue
client # go run client.go counterA 3
Continue
client # go run client.go counterA 4 //counterA十秒内数字和>10
Done

client # go run client.go counterB 4 //超时10秒总和未达到10
Continue

用go自带的库实现http服务器端server.go:

package main

import (
	"fmt"
	"net/http"
	"log"
	"os"
//	"os/signal"
	"g10086"
	"bufio"
	"io"
	"strings"
	"time"
	"encoding/json"
	"strconv"
//	"syscall"
)

//g10086 location 记录的配置文件
const g10086_save = "g10086.status"

//查看当前g10086的全局状态信息
func rootHandler (w http.ResponseWriter, r * http.Request) {
	fmt.Fprintf(w, "g_status: %d\n", len(g10086.G_status))

	for key,val := range g10086.G_status {
		fmt.Fprintf(w, "%s : %s\n", key, val)
	}
}

//将全局状态信息表存储到文件中
func saveHandler (w http.ResponseWriter, r * http.Request) {
	save_status()
	io.WriteString(w, "Save OK!")
}

//从文件加载信息
func load_status () {
	g10086.G_status = make(map[string] string)

	f, err := os.OpenFile(g10086_save, os.O_RDWR|os.O_CREATE, 0666)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	r := bufio.NewReader(f)  
        line, _, err := r.ReadLine()  
        for err == nil {  
		if info := strings.Split(string(line)," "); len(info) > 1 {
			g10086.G_status[info[0]] = info[1]
		}
                line, _, err = r.ReadLine()  
        }  
}

func save_status () {
	f, err := os.OpenFile(g10086_save, os.O_CREATE|os.O_RDWR, 0666) 
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	b := bufio.NewWriter(f) 
	for key,value := range g10086.G_status {
		line := key + " " + value + "\n"
		if n, err := b.WriteString(line); err != nil || n != len(line) {  
                	log.Fatal(err)  
        	}
	}
	if err = b.Flush(); err != nil {  
                log.Fatal(err)  
        } 
}

//查看全局状态信息是否有超时的信息,如果有,删除并记录日志
func check_timeout() {
	cur := time.Now().Unix()
	
	for key,value := range g10086.G_status {
		var cur_down g10086.Dstate //不能放在for循环之前!
		dec := json.NewDecoder(strings.NewReader(value))
		if err := dec.Decode(&cur_down); err != nil {
			return
		}
		for k,_ := range cur_down.Info {
			t, err := strconv.Atoi(k)
			if err != nil {
				return
			}
			if t < int(cur - 10) {
				delete(g10086.G_status, key)
				log.Println(key + " timedout")
				break
			}
		}
	}
}

//定时器,每1秒钟运行一次,检测超时
func timer () {
	for {
		timer := time.NewTicker(1 * time.Second)
		for {
			select {
			case <- timer.C:
				check_timeout()
			}
		}
	}
}

//配置服务器,监听端口和location
func main () {

	load_status () 

	go timer()
	defer save_status()

	http.HandleFunc("/",rootHandler)
	http.HandleFunc("/g10086",g10086.G10086Handler)
	http.HandleFunc("/save",saveHandler)

	log.SetOutput(os.Stdout)

	err := http.ListenAndServe("127.0.0.1:8088", nil)
	if err != nil {
		log.Fatal("ListenAndServe:", err)
	}
}

g10086/g10086.go 模块代码如下

package g10086

import (
	"io"
	"net/http"
	"strings"
	"strconv"
	"encoding/json"
	"time"
)

//全局计数器信息
var G_status map[string] string

//
type Dstate struct {
	id string
	status string
	Info map[string] string
}

//更新计数状态,如果计数器A的数字总和超过10,则输出完毕,删除此计数器
func updateStatus (key string, down Dstate) int {

	total := 0

	for _,v := range down.Info {
		n, err := strconv.Atoi(v)
		if err != nil {
			return -1
		}
		total += n
		if total > 10 {
			down.status = "Done"
			break
		}
	}

	if (down.status == "Done") {
		if _, ok := G_status[key]; ok {
			delete(G_status,key)
		}

		return 1
	} else {
		downinfo, err := json.Marshal(down)
		if err == nil {
			G_status[key] = string(downinfo)
		}
		return 0
	}
}

func G10086Handler (w http.ResponseWriter, r *http.Request) {

	key, val := r.PostFormValue("key"), r.PostFormValue("value")
	if key == "" || val == "" {
		io.WriteString(w,"no para")
		return
	}

	//查询之前有无对应key的计数器,如果有,则添加记录,如果没有,新建记录
	var cur_down Dstate
	if v, ok := G_status[key]; ok {
		dec := json.NewDecoder(strings.NewReader(v))
		if err := dec.Decode(&cur_down); err != nil {  
            		return
		}
		cur_down.Info[strconv.Itoa(int(time.Now().Unix()))] = val
	} else {
		new_status := map[string] string{strconv.Itoa(int(time.Now().Unix())):val}
		cur_down = Dstate{id:key, status:"Start", Info:new_status}
	}
	res := updateStatus(key, cur_down)

	switch res {
	case 1:
		io.WriteString(w, "Done" + key)
	case 0:
		io.WriteString(w, "Continue " + key)
	default:
		io.WriteString(w, "Unknown")
	}
}

client端代码如下:

package main

import (
	"net/http"
	"net/url"
	"log"
	"os"
)

func main () {

	if len(os.Args) < 3 {
		log.Fatal("para error")
	}
	key, val := os.Args[1], os.Args[2]

	resp, err := http.PostForm("http://127.0.0.1:8088/g10086",
			url.Values{"key": {key}, "value": {val}})
	if err != nil {
		log.Fatal("Post error : ", err)
	}

	if resp.StatusCode == 200 {
		resp.Write(os.Stdout)
	}
}


//使用示例
//go run client.go countA 3
//go run client.go countB 4

静态文件需要添加如下代码,创建template目录,将静态资源放在目录中

http.Handle("/template/", http.StripPrefix("/template/", http.FileServer(http.Dir("./template"))))

 同样的静态资源小文件放在nginx和go的性能测试如下:Request Per Second(nginx为7652)(go为5321)

定时器使用如下:

import "time"

func timer () {
        for {
                timer := time.NewTicker(5 * time.Second)
                for {
                        select {
                        case <- timer.C:
                                fmt.Print("timer called\n")
                        }
                }
        }
}

 JSON操作

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "log"
    "strings"
)

func main() {
    const jsonStream = `
        {"Name": "Ed", "Text": "Knock knock."}
        {"Name": "Sam", "Text": "Who's there?"}
        {"Name": "Ed", "Text": "Go fmt."}
        {"Name": "Sam", "Text": "Go fmt who?"}
        {"Name": "Ed", "Text": "Go fmt yourself!"}
    `
    type Message struct {
        Name, Text string
    }
    //json decode
    dec := json.NewDecoder(strings.NewReader(jsonStream))
    var m Message
    for {
        if err := dec.Decode(&m); err == io.EOF {
            break
        } else if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("%s: %s\n", m.Name, m.Text)
    }
    //json encode
    dataStream, err := json.Marshal(m)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Print(string(dataStream))
}
分享到:
评论

相关推荐

    用状态机实现任意编码计数器

    在7进制计数器中,通常只有一个输入——“时钟”(CLK),当时钟脉冲到来时,计数器会从当前状态转换到下一个状态。输出则是当前状态的编码值。 接下来,我们需要创建状态转换表,它定义了在给定输入下,每个状态...

    verilog实现60进制计数器

    在本主题中,我们关注的是一个特殊类型的计数器——60进制计数器,这种计数器在特定的计算或通信应用中可能会被用到,例如在基于六十进制(如古代巴比伦系统)的时间或角度表示中。60进制计数器不同于常见的二进制、...

    数电实验7——计数器. 报告docx.pdf

    【数电实验7——计数器】报告详细解析 本次实验是关于数字电子技术的实践,主要关注计数器的设计与应用。计数器在数字系统中起着至关重要的作用,能够实现对输入脉冲的计数,广泛应用于时序逻辑电路中。实验的核心...

    用集成计数器实现任意进制计数器——六进制.ms13

    用集成计数器实现任意进制计数器——六进制.ms13

    单片机课程设计——0~999999——百万计数器(仿真代码).zip

    在这个项目中,我们关注的是一个特殊的计数器设计,它可以计数从0到999999,即百万计数器。这个设计不仅考验了单片机的处理能力和存储资源,还涉及到实时系统和数字电路的知识。 首先,让我们了解单片机的基本概念...

    VHDL语言实现的计数器

    在本项目中,“VHDL语言实现的计数器”指的是利用VHDL编写代码,实现一个在FPGA(Field-Programmable Gate Array)开发板上工作的计数器,该计数器能够进行十进制计数,并将结果显示在7段数码管上。这里涉及到的知识...

    时序逻辑电路——60进制同步计数器的实现

    "时序逻辑电路——60进制同步计数器的实现" 时序逻辑电路是数字电路的核心组件之一,它可以实现各种数字逻辑操作和数据处理。 本文将介绍时序逻辑电路在实现60进制同步计数器中的应用。 一、时序逻辑电路简介 ...

    FPGA高速接口设计之SpaceWire——发送模块 fpga开发.pdf

    FPGA高速接口设计之SpaceWire——发送模块 FPGA开发是一个复杂的设计,涉及到发送模块的概述、发送模块的功能、发送状态机和流控机制等方面。该设计需要对SpaceWire协议和FPGA高速接口设计有深入的了解和理解。

    用Verilog设计实现异步双向计数器

    本文聚焦于使用Verilog设计实现异步双向计数器的技术细节,这一设计不仅体现了Verilog的强大功能,同时也满足了特定应用需求,如接口模块设计中对双向计数、异步置数、清零等功能的需求。 #### 异步双向计数器概述 ...

    verilog 0——9999计数器

    verilog 0——9999计数器 并能在数码管中显示出来

    采用RAM实现计数器及FPGA功能

    这个模块通过逻辑门电路或计数逻辑实现,确保正确的时序信号被传递到计数器和RAM。 3. **RAM模块**:该模块负责存储计数器的初始值和暂停时的计数值。它需要包含地址选择逻辑,使得计数器的输出能够根据地址输入...

    单片机课程设计——基于T_CO的计数器设计(仿真代码).zip

    在这个项目中,我们将探讨如何利用单片机的内部资源,特别是T_CO模块,来设计一个实用的计数器,并通过仿真验证其功能。 首先,我们要理解单片机中的计数器工作原理。计数器通常是由单片机内部的定时器模块驱动,...

    基于计数器宏功能模块设计一个模24方向可控计数器电路

    总结来说,基于计数器宏功能模块设计的模24方向可控计数器电路是一项综合了数字逻辑设计、硬件描述语言编程和FPGA实现技术的任务。这种计数器在各种应用场景中都有其独特价值,比如在数字信号处理、通信系统和自动化...

    实验五计数器的设计——实验报告.pdf

    实验五的目的是深入理解 JK 触发器的逻辑功能,并掌握如何使用 JK 触发器设计同步和异步计数器。计数器是数字系统中的核心组件,用于跟踪时间序列或数量的变化。JK 触发器是一种双稳态电路,能够实现翻转、置零、...

    FPGA课程设计——十进制计数器.zip

    本课程设计的主题是利用FPGA实现一个十进制计数器,这一主题涵盖了数字电路设计、FPGA基础、硬件描述语言(HDL)以及综合与仿真等多个关键知识点。 十进制计数器是一种能够进行从0到9循环计数的电路,它是数字系统...

    10进制计数器_计数器_

    这里我们关注的是一个4位宽的十进制计数器,它是用Verilog硬件描述语言实现的。Verilog是一种广泛使用的系统级语言,用于描述数字系统的硬件行为,包括逻辑门、触发器、计数器等各种数字电路。 首先,让我们了解十...

Global site tag (gtag.js) - Google Analytics