하나의 TCP 장거리 연결 장치 관리 백그라운드 프로젝트(8)
7579 단어 golangpostgresqltcp
전편
하나의 TCP 장거리 연결 장치 관리 백그라운드 프로젝트(一) 하나의 TCP 장거리 연결 장치 관리 백그라운드 프로젝트(二) 하나의 TCP 장거리 연결 장치 관리 백그라운드 프로젝트(3) 하나의 TCP 장거리 연결 장치 관리 백그라운드 프로젝트(4) 하나의 TCP 장거리 연결 장치 관리 백그라운드 프로젝트(5) 하나의 TCP 장거리 연결 장치 관리 백그라운드 프로젝트(6) 하나의 TCP 장거리 연결 장치 관리 백그라운드 프로젝트(7)
Github 저장소 주소
TCP 서버
앞의 모든 내용은 jtt808 프로토콜을 바탕으로 하는 TCP 서버를 실현하기 위한 작업입니다. 저희가 지금 필요로 하는 것은 위에서 설명한 내용을 통합하여 각 모듈이 업무를 조율하고 전체적인 서비스 절차를 완성하도록 하는 것입니다.
로딩 구성
먼저 프로필 불러오기를 말해 보세요. 한 응용 프로그램에 대해 유연성을 높이기 위해서는 프로필을 사용해야 합니다.종합적으로 고려하여 저는 toml 형식의 프로필을 사용하고 해석 라이브러리는 "github.com/BurntSushi/toml"를 사용합니다
# config
[tcp]
ip = ""
port = 19903
[web]
ip = ""
port = 8080
[map]
appKey = "your baidu map key"
[postgresql]
hostname="localhost"
tablename="pqgodb"
user="pqgotest"
password="pqgotest"
구성에는 구성에 적합한 구조체를 정의하는 전체 적용 구성이 포함됩니다.
type Config struct {
TcpCfg TcpConfig `toml:"tcp"`
WebCfg WebConfig `toml:"web"`
MapCfg MapConfig `toml:"map"`
PgCfg PgConfig `toml:"postgresql"`
}
type TcpConfig struct {
Ip string
Port int
}
type WebConfig struct {
Ip string
Port int
}
type MapConfig struct {
AppKey string
}
type PgConfig struct {
Hostname string
Tablename string
User string
Password string
}
var config Config
로딩 구성
curpath := GetCurrentDirectory()
_, err = toml.DecodeFile(curpath+"/config.toml", &config)
if err != nil {
log.Info("config error: ", err)
return
}
여기서 GetCurrentDirectory는 현재 적용되는 절대 경로를 가져옵니다.
func GetCurrentDirectory() string {
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
log.Fatal(err)
return ""
}
return strings.Replace(dir, "\\", "/", -1) // \ /
}
TCP 연결 관리
이 부분은 기본적으로 앞의 백엔드 모델의 설명과 일치한다.
var connManger map[string]*term.Terminal
connManger = make(map[string]*term.Terminal)
서버를 만들까,listen과accept를 만들까
address := config.TcpCfg.Ip + ":" + strconv.FormatInt(int64(config.TcpCfg.Port), 10)
log.Info("address port ", address)
listenSock, err := net.Listen("tcp", address)
if err != nil {
log.WithFields(logrus.Fields{"Error:": err.Error()}).Error("check")
os.Exit(1)
}
defer listenSock.Close()
for {
newConn, err := listenSock.Accept()
if err != nil {
continue
}
go recvConnMsg(newConn)
}
recvConnMsg 처리 TCP 클라이언트 데이터 수신
func recvConnMsg(conn net.Conn){
}
먼저 터미널을 만들고 connManager에 추가합니다.
buf := make([]byte, 0)
addr := conn.RemoteAddr()
log.WithFields(logrus.Fields{"network": addr.Network(), "ip": addr.String()}).Info("recv")
var t *term.Terminal = &term.Terminal{
Conn: conn,
Engine: engine,
Ch: make(chan int),
}
connManger[addr.String()] = t
ipaddress = addr.String()
TCP가 분리되면 connManager에서 해당 요소를 제거해야 합니다.
defer func() {
delete(connManger, addr.String())
conn.Close()
}()
그 다음은 데이터를 반복해서 읽고 처리하는 것이다.
for {
tempbuf := make([]byte, 1024)
}
데이터를 읽습니다. 이 데이터는 지난번에 처리되지 않은 데이터와 결합해야 합니다. 왜냐하면 패키지 해체가 있을 수 있기 때문입니다.
n, err := conn.Read(tempbuf)
if err != nil {
log.WithFields(logrus.Fields{"network": addr.Network(), "ip": addr.String()}).Info("closed")
return
}
buf = append(buf, tempbuf[:n]...)
var outlog string
for _, val := range buf {
outlog += fmt.Sprintf("%02X", val)
}
log.WithFields(logrus.Fields{"data": outlog}).Info("
필터를 호출하여 수신된 데이터를 처리하고 이미 사용된 바이트를 오프셋합니다.
var msg []proto.Message
var lens int
msg, lens, err = proto.Filter(buf)
if err != nil {
//
}
buf = buf[lens:]
msg는 메시지 슬라이스로 이 슬라이스에 있는 메시지를 순환 처리합니다. 모두 처리될 때까지:
for len(msg) > 0 {
//
sendBuf := t.Handler(msg[0])
if sendBuf != nil {
outlog = ""
for _, val := range sendBuf {
outlog += fmt.Sprintf("%02X", val)
}
log.WithFields(logrus.Fields{"data": outlog}).Info("---> ")
logframe := &LogFrame{
Stamp: time.Now(),
Dir: 1,
Frame: outlog,
}
_, err = engine.Insert(logframe)
if err != nil {
log.WithFields(logrus.Fields{"error": err.Error()}).Info("insert")
}
conn.Write(sendBuf)
msg = msg[1:]
}
}
메시지 처리는 프로세서를 호출합니다. 프로세서는 응답해야 할 데이터를 되돌려줍니다. 프로세서가 되돌려주는 데이터를 conn. Write를 통해 대응하는 tcp에 보내면 응답에 성공합니다.
이것이 바로 전체 tcp 서버의 기본 모델이다.
실행 중인 실제 로그 상황:
time="2019-12-31T17:53:52+08:00" level=info msg="address port :8080"
[GIN-debug] Listening and serving HTTP on :8080
time="2019-12-31T17:54:01+08:00" level=info msg=recv ip="127.0.0.1:38936" network=tcp
time="2019-12-31T17:54:01+08:00" level=info msg=" " data=7E80014005018986041210187042775504B004B0010200C77E
time="2019-12-31T17:54:03+08:00" level=info msg=" " data=7E80014005018986041210187042775504B104B1020000C67E
time="2019-12-31T17:54:05+08:00" level=info msg=" " data=7E80014005018986041210187042775504B204B2020000C67E
time="2019-12-31T17:54:08+08:00" level=info msg=" " data=7E80014005018986041210187042775504B304B3020000C67E
time="2019-12-31T17:54:11+08:00" level=info msg=" " data=7E80014005018986041210187042775504B404B4020000C67E
time="2019-12-31T17:54:13+08:00" level=info msg=" " data=7E80014005018986041210187042775504B504B5000200C67E
time="2019-12-31T17:54:16+08:00" level=info msg=" " data=7E80014005018986041210187042775504B604B6020000C67E
time="2019-12-31T17:54:21+08:00" level=info msg=" " data=7E80014005018986041210187042775504B704B7020000C67E
time="2019-12-31T17:54:26+08:00" level=info msg=" " data=7E80014005018986041210187042775504B804B8020000C67E
time="2019-12-31T17:54:31+08:00" level=info msg=" " data=7E80014005018986041210187042775504B904B9020000C67E
time="2019-12-31T17:54:36+08:00" level=info msg=" " data=7E80014005018986041210187042775504BA04BA020000C67E
time="2019-12-31T17:54:41+08:00" level=info msg=" " data=7E80014005018986041210187042775504BB04BB020000C67E
time="2019-12-31T17:54:42+08:00" level=info msg=" " data=7E80014005018986041210187042775504BC04BC000200C67E
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
set containerThere is no built-in set container in Go How to implement Set struct{} => type struct{}{} => 0bytes How to create set :=...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.