du94414 2013-07-20 13:16
浏览 39
已采纳

套接字回显服务器

I'm trying to implement a simple socket echo server in go this is the code:

package main

import (
    "fmt"
    "net"
    "sync"
)

func echo_srv(c net.Conn, wg sync.WaitGroup) {
    defer c.Close()
    defer wg.Done()

    for {
            var msg []byte

            n, err := c.Read(msg)
            if err != nil {
                    fmt.Printf("ERROR: read
")
                    fmt.Print(err)
                    return
            }
            fmt.Printf("SERVER: received %v bytes
", n)

            n, err = c.Write(msg)
            if err != nil {
                    fmt.Printf("ERROR: write
")
                    fmt.Print(err)
                    return
            }
            fmt.Printf("SERVER: sent %v bytes
", n)
    }
}

func main() {
    var wg sync.WaitGroup

    ln, err := net.Listen("unix", "./sock_srv")
    if err != nil {
            fmt.Print(err)
            return
    }
    defer ln.Close()

    conn, err := ln.Accept()
    if err != nil {
            fmt.Print(err)
            return
    }
    wg.Add(1)
    go echo_srv(conn, wg)

    wg.Wait()
}

For some reason as soon as a client connects, c.Read() does not block and the error message is printed. So, my first question is: Shouldn't c.Read() block until a client sends something to the socket?

And second: After printing the error message, the server does not terminate. This is what I see when executing the program in gdb:

(gdb) run                                                                    
Starting program: src/sockets/server/server                                  
warning: Could not load shared library symbols for linux-vdso.so.1.          
Do you need "set solib-search-path" or "set sysroot"?                        
[Thread debugging using libthread_db enabled]                                
Using host libthread_db library "/usr/lib/libthread_db.so.1".                
[New Thread 0x7fffe7806700 (LWP 28594)]                                      
[New Thread 0x7fffe7005700 (LWP 28595)]                                      
ERROR: read                                                                  
EOF^C                                                                        
Program received signal SIGINT, Interrupt.                                   
runtime.epollwait () at /usr/lib/go/src/pkg/runtime/sys_linux_amd64.s:383    
383             RET                                                          
(gdb) info goroutines                                                        
  1  waiting runtime.park                                                    
  2  syscall runtime.goexit                                                  
* 3  syscall runtime.entersyscallblock

I have similar echo servers in Python and C and they work fine. For completeness I also post the socket client application below (it works fine with my C and Python servers).

Client:

package main

import (
    "bufio"
    "fmt"
    "net"
    "os"
    "strings"
)

func main() {
    stdin := bufio.NewReader(os.Stdin)

    conn, err := net.Dial("unix", "./sock_srv")
    if err != nil {
            fmt.Print(err)
            return
    }
    defer conn.Close()

    for {
            fmt.Print("Enter message to transmit: ")
            msg, err := stdin.ReadString('
')
            if err != nil {
                    fmt.Print(err)
                    return
            }

            msg = msg[:len(msg)-1]
            if (strings.ToLower(msg) == "quit") || (strings.ToLower(msg) == "exit") {
                    fmt.Println("bye")
                    return
            }

            n, err := conn.Write([]byte(msg))
            if err != nil {
                    fmt.Print(err)
                    return
            }
            fmt.Printf("CLIENT: sent %v bytes
", n)

            n, err = conn.Read([]byte(msg))
            if err != nil {
                    fmt.Print(err)
                    return
            }
            fmt.Printf("CLIENT: received %v bytes
", n)

            fmt.Println("Received message:", msg)
    }
}

展开全部

  • 写回答

2条回答 默认 最新

  • doudou6719 2013-07-20 14:32
    关注

    Here is a working echo_srv for you. You'll need @jnml's suggestion too!

    • actually allocate some buffer to receive into - you made a 0 byte buffer!
    • exit neatly on EOF
    • only write the bytes received with msg[:n]

      func echo_srv(c net.Conn, wg *sync.WaitGroup) {
          defer c.Close()
          defer wg.Done()
      
          for {
              msg := make([]byte, 1000)
      
              n, err := c.Read(msg)
              if err == io.EOF {
                  fmt.Printf("SERVER: received EOF (%d bytes ignored)
      ", n)
                  return
              } else  if err != nil {
                  fmt.Printf("ERROR: read
      ")
                  fmt.Print(err)
                  return
              }
              fmt.Printf("SERVER: received %v bytes
      ", n)
      
              n, err = c.Write(msg[:n])
              if err != nil {
                  fmt.Printf("ERROR: write
      ")
                  fmt.Print(err)
                  return
              }
              fmt.Printf("SERVER: sent %v bytes
      ", n)
          }
      }
      

    展开全部

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)
编辑
预览

报告相同问题?

悬赏问题

  • ¥15 robocopy文件复制
  • ¥15 unity安卓打包出现问题
  • ¥15 爱快路由器端口更改错误导致无法访问
  • ¥20 安装catkin时遇到了如下问题请问该如何解决呢
  • ¥15 VAE模型如何输出结果
  • ¥15 编译python程序为pyd文件报错:{"source code string cannot contain null bytes"
  • ¥20 关于#r语言#的问题:广义加行模型拟合曲线后如何求拐点
  • ¥15 fluent设置了自动保存后,会有几个时间点不保存
  • ¥20 激光照射到四象线探测器,通过液晶屏显示X、Y值
  • ¥50 数据库开发问题求解答
手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部