bufio扫描仪并处理新行

我有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面的这种方法是否正确,但是上面包含了我的代码。我看到了一些实现,但是很多实现似乎依赖于关闭连接来开始处理请求,这不适合我的情况。

感谢任何指针,谢谢。

alfud0324 回答:bufio扫描仪并处理新行

您的通信“协议”(一行仅是一条消息,而不是一个协议)显然不能处理二进制数据。如果要在协议中发送文本数据,则可以将二进制数据转换为文本,例如使用Base64编码。您还需要一些语义来指示某些文本是从二进制转换而成的。

或者您可以更改协议以本地处理二进制数据。您可以将二进制数据的长度放在后面,这样您就知道必须将此数据读取为二进制数据,而不必将换行符解释为消息的结尾。

有许多协议可以很好地完成此任务,也许您不需要提出自定义协议。如果要发送文本消息,HTTP非常简单易用,则可以将数据格式化为JSON,使用Base64将二进制数据转换为文本:

{
    "command": "string","args": [
        "binaryDataAsBase64"
    ]
}
本文链接:https://www.f2er.com/3162014.html

大家都在问