diff --git a/business/jxstore/event/event.go b/business/jxstore/event/event.go
index f47a6f85d..886945f4d 100644
--- a/business/jxstore/event/event.go
+++ b/business/jxstore/event/event.go
@@ -45,7 +45,7 @@ func init() {
clientsHeart := make(map[string]*websocket.Conn)
wsClient.Clients = clients
wsClient.ClientsHeart = clientsHeart
- wsClient.s = new(sync.RWMutex)
+ wsClient = new(sync.RWMutex)
go handleMessages()
}
@@ -100,7 +100,7 @@ func ImMessage(userID string, ws *websocket.Conn) (err error) {
if len(messageGroups) == 0 {
return
}
- wsClient.s.Lock()
+ wsClient.Lock()
clientUser[userID] = ws
wsClient.ClientsHeart[userID] = ws
for _, v := range messageGroups {
@@ -110,7 +110,7 @@ func ImMessage(userID string, ws *websocket.Conn) (err error) {
wsClient.Clients[v.GroupID] = clientUser
}
}
- wsClient.s.Unlock()
+ wsClient.Unlock()
globals.SugarLogger.Debugf("userID :%v ,clients :%v", userID, utils.Format4Output(wsClient.Clients, false))
var s *model.ImMessageRecord
@@ -173,9 +173,9 @@ func ImMessage(userID string, ws *websocket.Conn) (err error) {
}
func GetOnlineUserCount() (count int) {
- wsClient.s.RLock()
+ wsClient.RLock()
count = len(wsClient.ClientsHeart)
- wsClient.s.RUnlock()
+ wsClient.RUnlock()
return count
}
diff --git a/business/jxstore/event/event_tcp.go b/business/jxstore/event/event_tcp.go
index d375f2a20..b5007d150 100644
--- a/business/jxstore/event/event_tcp.go
+++ b/business/jxstore/event/event_tcp.go
@@ -11,131 +11,13 @@ import (
"git.rosy.net.cn/jx-callback/globals"
"io"
"net"
- "regexp"
"strconv"
"strings"
- "sync"
"time"
)
-const (
- heartText = "1e000f02000151"
- printText = "1e00180200"
- printSuccessText = "1e001802000150"
-
- printErrWithoutPaper = "05"
-
- printMsgAlreadySend = 2 //已经发出打印消息
- printMsgSuccess = 1 //打印成功
- printMsgWait = 0 //待打印
- printMsgFail = -1 //打印失败(打印机报出)
- printMsgErr = -2 //京西报出
- printMsgAlreadyLoad = 3 //已放入队列
-
- heartErrNormal = "00" //正常
- heartErrWithoutPaper = "04" //心跳错,缺纸
- heartErrHot = "08" //过热
-
- printerStatusOnlineWithoutPaper = 2 //在线缺纸
- printerStatusOnline = 1 //在线
- printerStatusOffline = -1 //离线
- printerStatusOverFlow = -2 //流量超了
-)
-
-//标签
-const (
- signBR = "
" //换行
- signCenter = "
" //居中
- signLeft = "" //居左
- signRight = "" //居右
- signBig = "" //字体放大
- signHighBig = "" //字体纵向放大
- signWideBig = "" //字体横向放大
- signQrCenter = "" //二维码居中
- signQrLeft = "" //二维码居左
- signQrRight = "" //二维码居右
- signSound = "" //声音
-
- hexSignBROrEXE = "0a"
- hexSignCenter = "1b6101"
- hexSignLeft = "1b6100"
- hexSignRight = "1b6102"
- hexSignNormal = "1b2100"
- hexSignBig = "1b2130"
- hexSignHighBig = "1b2110"
- hexSignWideBig = "1b2120"
- hexSignQrCenter = "1d5802"
- hexSignQrLeft = "1d5800"
- hexSignQrRight = "1d5804"
- hexSignQr = "1b5a000106" //"1b5a000106" 0600 : 后面二维码的字节数
- hexSignQrEnd = "000a1b40" //000a0a0a1b40
- hexSignSound = "1d6b40"
-
- byteSignBR = "3c62723e" //换行
- byteSignCenter = "3c63656e7465723e" //居中
- byteSignLeft = "3c6c6566743e" //居左
- byteSignRight = "3c72696768743e" //居右
- byteSignBig = "3c623e" //字体放大
- byteSignHighBig = "3c68623e" //字体纵向放大
- byteSignWideBig = "3c77623e" //字体横向放大
- byteSignQrCenter = "3c7172633e"
- byteSignQrLeft = "3c71726c3e"
- byteSignQrRight = "3c7172723e"
- byteSignSound = "3c736f756e643e"
-
- byteSignCenterE = "3c2f63656e7465723e" //居中
- byteSignLeftE = "3c2f6c6566743e" //居左
- byteSignRightE = "3c2f72696768743e" //居右
- byteSignBigE = "3c2f623e" //字体放大
- byteSignHighBigE = "3c2f68623e" //字体纵向放大
- byteSignWideBigE = "3c2f77623e" //字体横向放大
- byteSignQrCenterE = "3c2f7172633e"
- byteSignQrLeftE = "3c2f71726c3e"
- byteSignQrRightE = "3c2f7172723e"
- byteSignSoundE = "3c2f736f756e643e"
-)
-
-var (
- tcpClient = &TcpClient{}
-
- printErrMap = map[string]string{
- printErrWithoutPaper: "打印机缺纸!",
- }
-
- signMap = map[string]string{
- byteSignBR: hexSignBROrEXE,
- }
-
- regexpQrc = regexp.MustCompile(byteSignQrCenter + "(.*?)" + byteSignQrCenterE)
- regexpQrl = regexp.MustCompile(byteSignQrLeft + "(.*?)" + byteSignQrLeftE)
- regexpQrr = regexp.MustCompile(byteSignQrRight + "(.*?)" + byteSignQrRightE)
- regexpSound = regexp.MustCompile(byteSignSound + "(.*?)" + byteSignSoundE)
-
- printMsgChan = make(chan *model.PrintMsg, 1024)
- printMsgCallbackChan = make(chan string, 1024)
- printMsgChanFail = make(chan *model.PrintMsg)
-)
-
-type PrintInfo struct {
- C net.Conn
- Status int // 2 //在线缺纸 1 //在线 -1 //离线
- StatusTime time.Time
-}
-
-//连接的客户端,吧每个客户端都放进来
-type TcpClient struct {
- Clients map[string]*PrintInfo
- s *sync.RWMutex
-}
-
-type GetPrintStatus struct {
- PrintNo string //打印机编号
- AppID int
-}
-
func ListenTcp() {
- tcpClient.Clients = make(map[string]*PrintInfo)
- tcpClient.s = new(sync.RWMutex)
+ t := NewTcpClient()
l, err := net.Listen("tcp", ":8000")
if err != nil {
fmt.Println("listen error:", err)
@@ -143,20 +25,20 @@ func ListenTcp() {
}
globals.SugarLogger.Debugf("begin listenTcp port 8000......")
go HandleTcpMessages()
- go HandleCheckTcpHeart()
- go doPrint2(printMsgChan)
- //go doPrint(printMsgChanFail)
+ go t.HandleCheckTcpHeart()
+ go t.doPrint2(printMsgChan)
+ go t.doPrint(printMsgChanFail)
for {
c, err := l.Accept()
if err != nil {
fmt.Println("accept error:", err)
break
}
- go handleConn(c)
+ go t.handleConn(c)
}
}
-func handleConn(c net.Conn) {
+func (t *TcpClient) handleConn(c net.Conn) {
var (
printNo string //打印机编号
printStatus *GetPrintStatus
@@ -181,13 +63,13 @@ func handleConn(c net.Conn) {
if err = json.Unmarshal(buffer[:n], &printStatus); err == nil {
fmt.Println("handleConn msg: ", string(buffer[:n]))
if printStatus != nil {
- var status int
- if tcpClient.Clients[printStatus.PrintNo] != nil {
- status = tcpClient.Clients[printStatus.PrintNo].Status
- } else {
- status = printerStatusOffline
- }
- globals.SugarLogger.Debugf("handleConn getstatus :%v", utils.Format4Output(tcpClient.Clients[printStatus.PrintNo], true))
+ status := t.getPrintStatus(printStatus.PrintNo)
+ //if t.Clients[printStatus.PrintNo] != nil {
+ // status = t.Clients[printStatus.PrintNo].Status
+ //} else {
+ // status = printerStatusOffline
+ //}
+ //globals.SugarLogger.Debugf("handleConn getstatus :%v", utils.Format4Output(t.Clients[printStatus.PrintNo], true))
c.Write([]byte(utils.Int2Str(status)))
c.Close()
}
@@ -201,30 +83,34 @@ func handleConn(c net.Conn) {
printNo = string(printNoData)
globals.SugarLogger.Debugf("handleConn printno :[%v]", printNo)
status := printStatus2JxStatus(data[len(data)-8 : len(data)-6])
- if tcpClient.Clients[printNo] == nil {
- printInfo := &PrintInfo{
- C: c,
- Status: printStatus2JxStatus(data[len(data)-8 : len(data)-6]),
- StatusTime: time.Now(),
- }
- tcpClient.s.Lock()
- tcpClient.Clients[printNo] = printInfo
- tcpClient.s.Unlock()
+ if t.Clients[printNo] == nil {
+ //printInfo := &PrintInfo{
+ // C: c,
+ // Status: printStatus2JxStatus(data[len(data)-8 : len(data)-6]),
+ // StatusTime: time.Now(),
+ //}
+ //t.Lock()
+ //t.Clients[printNo] = printInfo
+ //t.Unlock()
+ t.addConn(c, printNo, printStatus2JxStatus(data[len(data)-8:len(data)-6]))
changePrinterStatus(printNo, status)
- if status > 0 {
- //printFail()
+ if status == printerStatusOnline {
+ printFail()
}
} else {
//改变打印机状态
- tcpClient.s.Lock()
+ //t.Lock()
+ //if t.Clients[printNo] != nil {
+ // if t.Clients[printNo].Status != status {
+ // t.Clients[printNo].Status = status
+ // }
+ // t.Clients[printNo].StatusTime = time.Now()
+ //}
+ //t.Unlock()
changePrinterStatus(printNo, status)
- if tcpClient.Clients[printNo] != nil {
- if tcpClient.Clients[printNo].Status != status {
- tcpClient.Clients[printNo].Status = status
- }
- tcpClient.Clients[printNo].StatusTime = time.Now()
+ if t.getPrintStatus(printNo) != status {
+ t.setPrintStatus(printNo, status)
}
- tcpClient.s.Unlock()
}
} else if strings.Contains(data, printText) {
globals.SugarLogger.Debugf("handleConn print callback: %v", data)
@@ -265,16 +151,14 @@ func printFail() (err error) {
var (
db = dao.GetDB()
)
- prints, _ := dao.GetPrintMsgs(db, []int{printMsgWait, printMsgFail, printMsgErr}, time.Now().Add(-time.Hour*3), time.Now(), 0, 999)
+ prints, _ := dao.GetPrintMsgs(db, []int{printMsgWait, printMsgFail, printMsgErr, printMsgAlreadyLoad, printMsgAlreadySend}, time.Now().Add(-time.Hour*3), time.Now(), 0, 999)
for _, printMsg := range prints {
- //printMsgChanFail <- printMsg
- printMsg.Status = printMsgAlreadyLoad
- dao.UpdateEntity(db, printMsg, "Status")
+ printMsgChanFail <- printMsg
}
return err
}
-func doPrint(printMsgChanFail chan *model.PrintMsg) (err error) {
+func (t *TcpClient) doPrint(printMsgChanFail chan *model.PrintMsg) (err error) {
var (
db = dao.GetDB()
)
@@ -287,25 +171,25 @@ func doPrint(printMsgChanFail chan *model.PrintMsg) (err error) {
)
if printMsg != nil {
if err = checkPrintMsg(db, printMsg); err == nil {
- tcpClient.s.RLock()
- if tcpClient.Clients[printMsg.PrintNo] != nil {
- if tcpClient.Clients[printMsg.PrintNo].Status == printerStatusOnline {
- if tcpClient.Clients[printMsg.PrintNo].C != nil {
- c = tcpClient.Clients[printMsg.PrintNo].C
- data, err = buildMsg(printMsg)
- }
- }
- }
- tcpClient.s.RUnlock()
- if c != nil {
+ //t.Lock()
+ //if t.Clients[printMsg.PrintNo] != nil {
+ // if t.Clients[printMsg.PrintNo].Status == printerStatusOnline {
+ // if t.Clients[printMsg.PrintNo].C != nil {
+ // c = t.Clients[printMsg.PrintNo].C
+ // data, err = buildMsg(printMsg)
+ // }
+ // }
+ //}
+ //t.Unlock()
+ if c = t.getPrintConn(printMsg.PrintNo); c != nil {
+ data, err = buildMsg(printMsg)
if _, err = c.Write(data); err != nil {
globals.SugarLogger.Debugf("handleTcpMessages err [%v]", err)
- delete(tcpClient.Clients, printMsg.PrintNo)
- c.Close()
+ t.delConn(printMsg.PrintNo)
+ //delete(t.Clients, printMsg.PrintNo)
+ //c.Close()
} else {
globals.SugarLogger.Debugf("handleTcpMessages success, data: %v", hex.EncodeToString(data))
- printMsg.Status = printMsgAlreadySend
- dao.UpdateEntity(db, printMsg, "Status", "Comment")
}
}
}
@@ -323,7 +207,7 @@ func printStatus2JxStatus(printStatus string) (status int) {
return status
}
-func changePrintMsg(data string) (err error) {
+func (t *TcpClient) changePrintMsg(data string) (err error) {
var (
db = dao.GetDB()
printNo, comment string
@@ -343,7 +227,7 @@ func changePrintMsg(data string) (err error) {
status = printMsgFail
comment = printErrMap[data[12:14]]
}
- if tcpClient.Clients[printNo] == nil {
+ if !t.isExist(printNo) {
return err
}
if printMsgs, err := dao.GetPrintMsgNoPage(db, printNo, orderNo); err != nil {
@@ -377,7 +261,7 @@ func HandleTcpMessages() {
}
}
-func doPrint2(printMsgChan chan *model.PrintMsg) (err error) {
+func (t *TcpClient) doPrint2(printMsgChan chan *model.PrintMsg) (err error) {
var (
db = dao.GetDB()
)
@@ -390,20 +274,33 @@ func doPrint2(printMsgChan chan *model.PrintMsg) (err error) {
)
if printMsg != nil {
if err = checkPrintMsg(db, printMsg); err == nil {
- tcpClient.s.RLock()
- if tcpClient.Clients[printMsg.PrintNo] != nil {
- if tcpClient.Clients[printMsg.PrintNo].Status == printerStatusOnline {
- if tcpClient.Clients[printMsg.PrintNo].C != nil {
- c = tcpClient.Clients[printMsg.PrintNo].C
- data, err = buildMsg(printMsg)
- }
- } else if tcpClient.Clients[printMsg.PrintNo].Status == printerStatusOffline {
- err = fmt.Errorf("打印机离线!")
- } else if tcpClient.Clients[printMsg.PrintNo].Status == printerStatusOnlineWithoutPaper {
- err = fmt.Errorf("打印机缺纸!")
+ //t.Lock()
+ //if t.Clients[printMsg.PrintNo] != nil {
+ // if t.Clients[printMsg.PrintNo].Status == printerStatusOnline {
+ // if t.Clients[printMsg.PrintNo].C != nil {
+ // c = t.Clients[printMsg.PrintNo].C
+ // data, err = buildMsg(printMsg)
+ // }
+ // } else if t.Clients[printMsg.PrintNo].Status == printerStatusOffline {
+ // err = fmt.Errorf("打印机离线!")
+ // } else if t.Clients[printMsg.PrintNo].Status == printerStatusOnlineWithoutPaper {
+ // err = fmt.Errorf("打印机缺纸!")
+ // }
+ //}
+ //t.Unlock()
+ status := t.getPrintStatus(printMsg.PrintNo)
+ switch status {
+ case printerStatusOnline:
+ if c = t.getPrintConn(printMsg.PrintNo); c != nil {
+ data, err = buildMsg(printMsg)
}
+ case printerStatusOffline:
+ err = fmt.Errorf("打印机离线!")
+ case printerStatusOnlineWithoutPaper:
+ err = fmt.Errorf("打印机缺纸!")
+ default:
+ err = fmt.Errorf("打印机状态未知!")
}
- tcpClient.s.RUnlock()
}
} else {
err = fmt.Errorf("未查询到此printMsg")
@@ -412,22 +309,24 @@ func doPrint2(printMsgChan chan *model.PrintMsg) (err error) {
printMsg.Status = printMsgErr
printMsg.Comment = err.Error()
dao.UpdateEntity(db, printMsg, "Status", "Comment")
- delete(tcpClient.Clients, printMsg.PrintNo)
- if c != nil {
- c.Close()
- }
+ t.delConn(printMsg.PrintNo)
+ //delete(t.Clients, printMsg.PrintNo)
+ //if c != nil {
+ // c.Close()
+ //}
} else {
if c != nil {
if _, err = c.Write(data); err != nil {
globals.SugarLogger.Debugf("handleTcpMessages err [%v]", err)
- delete(tcpClient.Clients, printMsg.PrintNo)
- c.Close()
+ t.delConn(printMsg.PrintNo)
+ //delete(t.Clients, printMsg.PrintNo)
+ //c.Close()
} else {
globals.SugarLogger.Debugf("handleTcpMessages success, data: %v", hex.EncodeToString(data))
printMsg.Status = printMsgAlreadySend
dao.UpdateEntity(db, printMsg, "Status", "Comment")
dataStr := <-printMsgCallbackChan
- changePrintMsg(dataStr)
+ t.changePrintMsg(dataStr)
}
}
}
@@ -436,10 +335,10 @@ func doPrint2(printMsgChan chan *model.PrintMsg) (err error) {
return err
}
-func HandleCheckTcpHeart() {
+func (t *TcpClient) HandleCheckTcpHeart() {
for {
keys := []string{}
- for k, v := range tcpClient.Clients {
+ for k, v := range t.Clients {
if time.Now().Sub(v.StatusTime) > time.Minute+time.Second {
v.Status = printerStatusOffline
keys = append(keys, k)
@@ -447,8 +346,8 @@ func HandleCheckTcpHeart() {
}
for _, v := range keys {
changePrinterStatus(v, printerStatusOffline)
- if tcpClient.Clients[v] != nil {
- delete(tcpClient.Clients, v)
+ if t.Clients[v] != nil {
+ delete(t.Clients, v)
}
}
}
diff --git a/business/jxstore/event/event_tcp_utils.go b/business/jxstore/event/event_tcp_utils.go
new file mode 100644
index 000000000..4d51048bf
--- /dev/null
+++ b/business/jxstore/event/event_tcp_utils.go
@@ -0,0 +1,189 @@
+package event
+
+import (
+ "git.rosy.net.cn/jx-callback/business/model"
+ "net"
+ "regexp"
+ "sync"
+ "time"
+)
+
+const (
+ heartText = "1e000f02000151"
+ printText = "1e00180200"
+ printSuccessText = "1e001802000150"
+
+ printErrWithoutPaper = "05"
+
+ printMsgAlreadySend = 2 //已经发出打印消息
+ printMsgSuccess = 1 //打印成功
+ printMsgWait = 0 //待打印
+ printMsgFail = -1 //打印失败(打印机报出)
+ printMsgErr = -2 //京西报出
+ printMsgAlreadyLoad = 3 //已放入队列
+
+ heartErrNormal = "00" //正常
+ heartErrWithoutPaper = "04" //心跳错,缺纸
+ heartErrHot = "08" //过热
+
+ printerStatusOnlineWithoutPaper = 2 //在线缺纸
+ printerStatusOnline = 1 //在线
+ printerStatusOffline = -1 //离线
+)
+
+//标签
+const (
+ signBR = "
" //换行
+ signCenter = "" //居中
+ signLeft = "" //居左
+ signRight = "" //居右
+ signBig = "" //字体放大
+ signHighBig = "" //字体纵向放大
+ signWideBig = "" //字体横向放大
+ signQrCenter = "" //二维码居中
+ signQrLeft = "" //二维码居左
+ signQrRight = "" //二维码居右
+ signSound = "" //声音
+
+ hexSignBROrEXE = "0a"
+ hexSignCenter = "1b6101"
+ hexSignLeft = "1b6100"
+ hexSignRight = "1b6102"
+ hexSignNormal = "1b2100"
+ hexSignBig = "1b2130"
+ hexSignHighBig = "1b2110"
+ hexSignWideBig = "1b2120"
+ hexSignQrCenter = "1d5802"
+ hexSignQrLeft = "1d5800"
+ hexSignQrRight = "1d5804"
+ hexSignQr = "1b5a000106" //"1b5a000106" 0600 : 后面二维码的字节数
+ hexSignQrEnd = "000a1b40" //000a0a0a1b40
+ hexSignSound = "1d6b40"
+
+ byteSignBR = "3c62723e" //换行
+ byteSignCenter = "3c63656e7465723e" //居中
+ byteSignLeft = "3c6c6566743e" //居左
+ byteSignRight = "3c72696768743e" //居右
+ byteSignBig = "3c623e" //字体放大
+ byteSignHighBig = "3c68623e" //字体纵向放大
+ byteSignWideBig = "3c77623e" //字体横向放大
+ byteSignQrCenter = "3c7172633e"
+ byteSignQrLeft = "3c71726c3e"
+ byteSignQrRight = "3c7172723e"
+ byteSignSound = "3c736f756e643e"
+
+ byteSignCenterE = "3c2f63656e7465723e" //居中
+ byteSignLeftE = "3c2f6c6566743e" //居左
+ byteSignRightE = "3c2f72696768743e" //居右
+ byteSignBigE = "3c2f623e" //字体放大
+ byteSignHighBigE = "3c2f68623e" //字体纵向放大
+ byteSignWideBigE = "3c2f77623e" //字体横向放大
+ byteSignQrCenterE = "3c2f7172633e"
+ byteSignQrLeftE = "3c2f71726c3e"
+ byteSignQrRightE = "3c2f7172723e"
+ byteSignSoundE = "3c2f736f756e643e"
+)
+
+var (
+ //t = &TcpClient{}
+
+ printErrMap = map[string]string{
+ printErrWithoutPaper: "打印机缺纸!",
+ }
+
+ signMap = map[string]string{
+ byteSignBR: hexSignBROrEXE,
+ }
+
+ regexpQrc = regexp.MustCompile(byteSignQrCenter + "(.*?)" + byteSignQrCenterE)
+ regexpQrl = regexp.MustCompile(byteSignQrLeft + "(.*?)" + byteSignQrLeftE)
+ regexpQrr = regexp.MustCompile(byteSignQrRight + "(.*?)" + byteSignQrRightE)
+ regexpSound = regexp.MustCompile(byteSignSound + "(.*?)" + byteSignSoundE)
+
+ printMsgChan = make(chan *model.PrintMsg, 1024)
+ printMsgCallbackChan = make(chan string, 1024)
+ printMsgChanFail = make(chan *model.PrintMsg)
+)
+
+type PrintInfo struct {
+ C net.Conn
+ Status int // 2 //在线缺纸 1 //在线 -1 //离线
+ StatusTime time.Time
+}
+
+//连接的客户端,吧每个客户端都放进来
+type TcpClient struct {
+ Clients map[string]*PrintInfo
+ *sync.RWMutex
+}
+
+type GetPrintStatus struct {
+ PrintNo string //打印机编号
+ AppID int
+}
+
+func (t *TcpClient) delConn(key string) {
+ t.Lock()
+ defer t.Unlock()
+
+ delete(t.Clients, key)
+ t.Clients[key].C.Close()
+}
+
+func (t *TcpClient) addConn(c net.Conn, key string, status int) {
+ t.Lock()
+ defer t.Unlock()
+
+ t.Clients[key] = &PrintInfo{
+ C: c,
+ Status: status,
+ StatusTime: time.Now(),
+ }
+}
+
+func (t *TcpClient) getPrintStatus(key string) int {
+ t.RLock()
+ defer t.RUnlock()
+ if t.isExist(key) {
+ return t.Clients[key].Status
+ } else {
+ return printerStatusOffline
+ }
+}
+
+func (t *TcpClient) getPrintConn(key string) net.Conn {
+ t.RLock()
+ defer t.RUnlock()
+ if t.isExist(key) {
+ return t.Clients[key].C
+ } else {
+ return nil
+ }
+}
+
+func (t *TcpClient) isExist(key string) bool {
+ t.RLock()
+ defer t.RUnlock()
+
+ if t.Clients[key] == nil {
+ return false
+ } else {
+ return true
+ }
+}
+
+func (t *TcpClient) setPrintStatus(key string, status int) {
+ t.Lock()
+ defer t.Unlock()
+
+ if t.isExist(key) {
+ t.Clients[key].Status = status
+ t.Clients[key].StatusTime = time.Now()
+ }
+}
+
+func NewTcpClient() *TcpClient {
+ return &TcpClient{
+ Clients: make(map[string]*PrintInfo),
+ }
+}