第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

函數(shù)中的循環(huán)問(wèn)題

函數(shù)中的循環(huán)問(wèn)題

Go
aluckdog 2022-07-18 15:51:23
我有一個(gè)小型 TCP 服務(wù)器正在運(yùn)行,用戶可以通過(guò) telnet 進(jìn)行連接。有一個(gè)“菜單”選項(xiàng)循環(huán)(例如觸發(fā)單個(gè)字符輸入),選擇“L”選項(xiàng)允許連接的用戶“留言”。然而:從連接菜單中進(jìn)行選擇 (L) 時(shí) - 它會(huì)復(fù)制/重復(fù)菜單然后,需要額外/不必要的按鍵才能看到回顯給用戶的類型我懷疑我有循環(huán)問(wèn)題,但我不知道它在哪里崩潰。有任何想法嗎?package mainimport (    "bytes"    "fmt"    "log"    "net")const (    port = "5555")var arr []stringtype Client struct {    c        net.Conn    dataType string    menuCurr string}func NewClient() *Client {    return &(Client{})}func waitForInput(didInput chan<- bool) {    // Wait for a valid input here    didInput <- true}func main() {    log.Printf("Hello Server!")    service := ":5555"    tcpAddr, error := net.ResolveTCPAddr("tcp", service)    if error != nil {        log.Printf("Error: Could not resolve address")    } else {        netListen, error := net.Listen(tcpAddr.Network(), tcpAddr.String())        if error != nil {            log.Fatal(error)        } else {            defer netListen.Close()            for {                log.Printf("Waiting for clients")                conn, error := netListen.Accept()                if error != nil {                    log.Print("Client error: ", error)                } else {                    log.Printf("Client connected %s -> %s \n", conn.RemoteAddr(), conn.LocalAddr())                    go handler(conn)                }            }        }    }}func removeClient(conn net.Conn) {    log.Printf("Client %s disconnected", conn.RemoteAddr())    conn.Close()}func handler(conn net.Conn) {    defer removeClient(conn)    errorChan := make(chan error)    dataChan := make(chan []byte)    // Set defaults for incoming connections    var s *Client    s = NewClient()    s.c = conn    s.dataType = "key"    s.menuCurr = "connect" // first menu every user sees
查看完整描述

2 回答

?
慕運(yùn)維8079593

TA貢獻(xiàn)1876條經(jīng)驗(yàn) 獲得超5個(gè)贊

所以你幾乎明白了!

  1. 需要額外按鍵的原因是您的選擇案例在收到另一個(gè)字符之前不會(huì)處理?;旧夏懵浜罅艘粋€(gè)角色。當(dāng)您從用戶那里收集消息時(shí),您還需要注意這一點(diǎn)。

這是我能夠開始工作的。我的 telnet 客戶端在我點(diǎn)擊返回之前不會(huì)發(fā)送(我在 Windows 上,為什么是 \r\n 而不是只是 \n)所以我需要去除那些額外的字符。

package main


import (

    "bytes"

    "fmt"

    "log"

    "net"

    "strings"

)


const (

    port = "5555"

)


var arr []string


type Client struct {

    c        net.Conn

    dataType string

    menuCurr string

}


func NewClient() *Client {

    return &(Client{})


}


func waitForInput(didInput chan<- bool) {

    // Wait for a valid input here


    didInput <- true

}


func main() {


    log.Printf("Hello Server!")

    service := ":5555"

    tcpAddr, error := net.ResolveTCPAddr("tcp", service)

    if error != nil {

        log.Printf("Error: Could not resolve address")

    } else {

        netListen, error := net.Listen(tcpAddr.Network(), tcpAddr.String())

        if error != nil {

            log.Fatal(error)

        } else {

            defer netListen.Close()

            for {

                log.Printf("Waiting for clients")

                conn, error := netListen.Accept()

                if error != nil {

                    log.Print("Client error: ", error)

                } else {

                    log.Printf("Client connected %s -> %s \n", conn.RemoteAddr(), conn.LocalAddr())

                    go handler(conn)

                }

            }

        }

    }

}


func removeClient(conn net.Conn) {


    log.Printf("Client %s disconnected", conn.RemoteAddr())

    conn.Close()

}


func handler(conn net.Conn) {


    defer removeClient(conn)

    errorChan := make(chan error)

    dataChan := make(chan []byte)


    // Set defaults for incoming connections

    var s *Client

    s = NewClient()

    s.c = conn

    s.dataType = "key"

    s.menuCurr = "connect" // first menu every user sees


    go readWrapper(conn, dataChan, errorChan)

    r := bytes.NewBuffer(make([]byte, 0, 1024))


    // default menu

    fmt.Fprintf(conn, "Select an option:\r\n\n[L] Leave Message\r\n[!] Disconnect\r\n\nCmd? ")


    for {

        select {

        case data := <-dataChan:

            // notice how i removed the current menu state


            // "key" responds to single character input

            if s.dataType == "key" {

                t := strings.TrimSuffix(strings.TrimSuffix(string(data), "\r\n"), "\n")

                switch t {

                default:

                    fmt.Println("client hit invalid key...")

                    // remove the continue since the menu prints at the bottom

                    // continue

                case "L", "l":

                    s.dataType = "text"

                    s.menuCurr = "message"


                    // notice the message here and the break instead of the continue.

                    // if we use continue instead it will wait until your user sends something

                    // with a break instead it will fall through and start collecting the text

                    fmt.Fprintf(conn, "Type a mesage. Escape to quit. \r\n\n")

                    break

                case "!":

                    fmt.Fprintf(conn, " Bye!")

                    fmt.Println("client chose to exit...")

                    // tell current menu to exit

                    s.menuCurr = "exit"

                }

            }


            // "Text" allows for free typing

            if s.dataType == "text" {

                for {

                    select {

                    case data := <-dataChan:

                        fmt.Fprintf(conn, string(data))

                        if bytes.Equal(data, []byte("\r\n")) || bytes.Equal(data, []byte("\r")) {

                            fmt.Fprintf(conn, "you typed: %q\r\n", r.String())

                            r.Reset()

                            s.dataType = "key"

                            s.menuCurr = "connect"

                            break

                        }

                        if bytes.Equal(data, []byte("\033")) || bytes.Equal(data, []byte("\033\r\n")) {

                            fmt.Fprintf(conn, "\r\nAborted!\r\n")

                            r.Reset()

                            s.dataType = "key"

                            s.menuCurr = "connect"

                            break

                        }

                        r.Write(data)

                    }

                    log.Printf("Client %s sent: %q", conn.RemoteAddr(), r.String())

                    if s.menuCurr == "connect" {

                        break

                    }

                }

            }


            if s.menuCurr == "connect" {

                fmt.Fprintf(conn, "Select an option:\r\n\n[L] Leave Message\r\n[!] Disconnect\r\n\nCmd? ")

            }

            // fall through statement to close connection

            if s.menuCurr == "exit" {

                break

            }


            // otherwise continue printing menu for invalid submissions

            continue


        case err := <-errorChan:

            log.Println("An error occured:", err.Error())

            return

        }

        fmt.Println("closing")

        break

    }

    conn.Close()

}


func readWrapper(conn net.Conn, dataChan chan []byte, errorChan chan error) {

    for {


        buf := make([]byte, 1024)

        reqLen, err := conn.Read(buf)

        if err != nil {

            errorChan <- err

            return

        }

        dataChan <- buf[:reqLen]


    }


}


查看完整回答
反對(duì) 回復(fù) 2022-07-18
?
楊魅力

TA貢獻(xiàn)1811條經(jīng)驗(yàn) 獲得超6個(gè)贊

使用 stocktelnet命令行程序時(shí),它通常會(huì)與服務(wù)器協(xié)商以在LINEMODE. 在這種模式下,為了節(jié)省帶寬,用戶輸入將被緩沖。當(dāng)用戶點(diǎn)擊時(shí),數(shù)據(jù)被刷新(即發(fā)送到服務(wù)器):

  • Enter; 或者

  • Ctrl-D

您可以在當(dāng)前狀態(tài)下使用您的服務(wù)器,但您必須鍵入擊鍵:L后跟Ctrl-D(強(qiáng)制刷新)。然后客戶端將收到預(yù)期的服務(wù)器響應(yīng):type your message.

您的服務(wù)器代碼需要單次擊鍵 ( L!),因此如果您點(diǎn)擊-L然后Enter服務(wù)器收到的消息將是L\r\n,這是您的服務(wù)器代碼出錯(cuò)的地方:

if s.dataType == "key" {

    switch string(data) {

        default:

            fmt.Printf("client hit invalid key... (%q)\n", string(data)) // <- `L\r\n`

            continue

        case "L", "l":

            s.dataType = "text"

            s.menuCurr = "message"

            continue

        case "!":

            fmt.Fprintf(conn, " Bye!")

            fmt.Println("client chose to exit...")

            break

    }

}


查看完整回答
反對(duì) 回復(fù) 2022-07-18
  • 2 回答
  • 0 關(guān)注
  • 126 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)