我有2个通过TCP套接字进行通信的进程。 A面向B面发送一个字符串,有时会使用标准的加密/密码包对其进行加密。结果字符串可能包含换行符,但是Side B的bufio扫描器将其解释为请求的结尾。我希望B面继续接受行,追加行并等待已知的命令结束字符,然后再进一步处理它。 B侧将向A侧返回响应,因此连接保持打开状态,因此不能将close-connection事件用作命令定界符。
对于单行命令,一切正常,但是加密输出中的这些新行字符会引起问题(大约10%的时间)。
A端将以以下格式发送(第三个是我尝试正确处理的问题字符串的合法示例):
callCommand()
callCommand(“一个”,“两个”,“三个”)
callCommand(“ string”,“ encrypted-data-to-follow”,“ [7b��Cr��l��G���bH�@x�����������(z �$�a�0��ڢ5 Y7 +��U�QT�llK�(n�U��J��qqB�BX�+ l \8H��-g.y.. �1�f�I�C��oxz�8?c�e�Tb�4�hDW��� �
我们可以完全肯定地说命令结束键是一个圆括号“)”和换行符。
A边发送到B边的功能:
func writer(text string) string {
conn,err := net.Dial("tcp",Tcpdest)
t := time.Now()
if err != nil {
if _,t := err.(*net.OpError); t {
fmt.Println("Some problem connecting.\r\n")
} else {
fmt.Println("Unknown error: " + err.Error()+"\r\n")
}
} else {
conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
_,err = conn.Write([]byte(text+"\r\n"))
if err != nil {
fmt.Println("Error writing to stream.\r\n")
} else {
timeNow := time.Now()
if timeNow.Sub(t.Add(time.Duration(5*time.Second))).Seconds() > 5 {
return "timeout"
}
scanner := bufio.NewScanner(conn)
for {
ok := scanner.Scan()
if !ok {
break
}
if strings.HasPrefix(scanner.Text(),"callCommand(") && strings.HasSuffix(scanner.Text(),")") {
conn.Close()
return scanner.Text()
}
}
}
}
return "unspecified error"
}
乙方对传入连接的处理:
src := "192.168.68.100:9000"
listener,_ := net.Listen("tcp",src)
defer listener.Close()
for {
conn,err := listener.accept()
if err != nil {
fmt.Println("Some connection error: %s\r\n",err)
}
go handleConnection(conn)
}
func handleConnection(conn net.Conn) {
remoteAddr := conn.RemoteAddr().String()
fmt.Println("Client connected from " + remoteAddr + "\r\n")
scanner := bufio.NewScanner(conn)
wholeString := ""
for {
ok := scanner.Scan()
if !ok {
break
}
//Trying to find the index of a new-line character,to help me understand how it's being processed
fmt.Println(strings.Index(scanner.Text(),"\n"))
fmt.Println(strings.Index(wholeString,"\n"))
//for the first line received,add it to wholeString
if len(wholeString) == 0 {
wholeString = scanner.Text()
}
re := regexp.MustCompile(`[a-zA-Z]+\(.*\)\r?\n?`)
if re.Match([]byte(wholeString)) {
fmt.Println("Matched command format")
handleRequest(wholeString,conn)
} else if len(wholeString) > 0 && !re.Match([]byte(wholeString)) {
//Since we didn't match regex,we can assume there's a new-line mid string,so append to wholeString
wholeString += "\n"+scanner.Text()
}
}
conn.Close()
fmt.Println("Client at " + remoteAddr + " disconnected.\r\n")
}
func handleRequest(request string,conn net.Conn) {
fmt.Println("Received: "+request)
}
我不确定B面的这种方法是否正确,但是上面包含了我的代码。我看到了一些实现,但是很多实现似乎依赖于关闭连接来开始处理请求,这不适合我的情况。
感谢任何指针,谢谢。