V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
awanganddong
V2EX  ›  Go 编程语言

用 go 实现 socket ,帮忙看看问题处在哪里

  •  
  •   awanganddong · 2021-04-06 22:50:06 +08:00 · 6998 次点击
    这是一个创建于 1337 天前的主题,其中的信息可能已经有所发展或是发生改变。
    package main
    
    import (
    	"bytes"
    	"fmt"
    	"net"
    	"time"
    )
    
    func main() {
    	listener, err := net.Listen("tcp", "127.0.0.1:9527")
    	defer listener.Close()
    	if err != nil {
    		fmt.Printf("server err %v\n", err)
    	} else {
    		for {
    			conn, err := listener.Accept()
    			if err == nil {
    				go handleConn(conn)
    			}
    		}
    	}
    }
    func Read(conn net.Conn) (string, error) {
    	readBytes := make([]byte, 1)
    	var buf bytes.Buffer
    	for {
    		_, err := conn.Read(readBytes)
    		if err != nil {
    			return "", err
    		}
    		readByte := readBytes[0]
    		if readByte == '\t' {
    			break
    		}
    	}
    	return buf.String(), nil
    }
    func Write(conn net.Conn, content string) (int, error) {
    	var buf bytes.Buffer
    	buf.WriteString(content)
    	buf.WriteByte('\t')
    	return conn.Write(buf.Bytes())
    }
    
    func handleConn(conn net.Conn) {
    	for {
    		conn.SetReadDeadline(time.Now().Add(2))
    		if str, err := Read(conn); err == nil {
    			fmt.Printf("收到的数据:%v\n", str)
    			Write(conn, "server got:"+str)
    		}else{
    			fmt.Printf("read err: %v\n",err)
    		}
    	}
    }
    
    

    现在用 telnet 发送消息,然后报错 read err: read tcp 127.0.0.1:9527->127.0.0.1:56508: i/o timeout

    14 条回复    2021-05-06 17:42:10 +08:00
    codehz
        1
    codehz  
       2021-04-06 22:55:28 +08:00
    time 的 add 默认单位是纳秒(
    awanganddong
        2
    awanganddong  
    OP
       2021-04-06 23:04:07 +08:00   ❤️ 1
    设置为以下还是同样报错
    conn.SetReadDeadline(time.Now().Add(10 * time.Second))
    codehz
        3
    codehz  
       2021-04-06 23:07:42 +08:00
    所以你发送的内容有没有包含制表符呢
    awanganddong
        4
    awanganddong  
    OP
       2021-04-06 23:09:24 +08:00   ❤️ 1
    @codehz 我把制表符剔除试下
    djoiwhud
        5
    djoiwhud  
       2021-04-07 01:44:10 +08:00 via Android
    我看了两分钟也没看出你这个 read 里面定义的 buf 是什么用途。
    每次读一个字节的操作看起来是学习练手的。看得出你没认真读过计算机网络卷一。

    另外 read 的 len 返回值务必处理。
    writesome6
        6
    writesome6  
       2021-04-07 09:43:13 +08:00
    其实就是你设置的超时时间有问题
    1000172
        7
    1000172  
       2021-04-07 10:45:53 +08:00
    我之前用框架写时遇到连不通是因为跨域的问题(因为我用网页测试,框架内默认进行跨域验证,我重写了跨域验证方法后就好了),你这个没太仔细看,只是送点参考意见
    bruce0
        8
    bruce0  
       2021-04-07 10:52:24 +08:00
    ```
    func Read(conn net.Conn) (string, error) {
    readBytes := make([]byte, 1)
    var buf bytes.Buffer
    for {
    _, err := conn.Read(readBytes)
    if err != nil {
    return "", err
    }
    readByte := readBytes[0]
    if readByte == '\t' {
    break
    }
    }
    return buf.String(), nil
    }
    ```
    readBytes := make([]byte, 1) 这里你创建的这个切片,长度是 1, 一般没有这样设置的. 一般都是客户端和服务端约定一个包最大长度,比如 1024, 每次客户端和服务端发的数据都不会超过这个最大长度,

    n, err := conn.Read(readBytes) 通过这个函数读的时候, 返回的 n 是这次读取的长度


    而你现在传了一个长度为 1 的切片, 假设这次客户端发来的数据长度为 10 因为你的切片长度为 1 就只能读到第位 后面的都丢了
    awanganddong
        9
    awanganddong  
    OP
       2021-04-07 12:55:35 +08:00
    以上是我参照别人 demo 写的,里边逻辑确实有问题。
    skiy
        10
    skiy  
       2021-04-07 12:56:14 +08:00
    你的 buf.String() 永远是""
    crescentBLADE
        11
    crescentBLADE  
       2021-04-08 18:11:26 +08:00
    你这是意识流
    awanganddong
        12
    awanganddong  
    OP
       2021-04-08 19:40:51 +08:00
    属于瞎几把写,我再重新修改修改,里边逻辑不太对
    awanganddong
        13
    awanganddong  
    OP
       2021-04-30 11:01:37 +08:00
    socket 属于流的模式
    这个要搞明白
    以下是修改的代码

    ```
    package main

    import (
    "fmt"
    "io"
    "net"
    )

    func main() {
    listener, err := net.Listen("tcp", "127.0.0.1:9527")
    if err != nil {
    fmt.Printf("server err %v\n", err)
    }
    defer listener.Close()
    for {
    conn, err := listener.Accept()
    if err == nil {
    go handleConn(conn)
    }
    }

    }

    func handleConn(conn net.Conn) {

    for {
    readBytes := make([]byte, 1)
    n, err := conn.Read(readBytes)
    if err != nil && err != io.EOF {
    fmt.Printf("read err:%v\n", err)
    break
    }
    fmt.Printf("read content:%v", readBytes[:n])
    _, err = conn.Write(readBytes[:n])
    if err != nil {
    fmt.Printf("write err:%v\n", err)
    break
    }
    }
    }

    ```
    who1996
        14
    who1996  
       2021-05-06 17:42:10 +08:00
    tcp 没有跨域,,跨域是因为 client 端的安全策略!!!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1063 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 22:20 · PVG 06:20 · LAX 14:20 · JFK 17:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.