免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1660 | 回复: 6

[其他] 求助,write两次只能read一次,如何解决呢? [复制链接]

论坛徽章:
0
发表于 2013-07-01 11:26 |显示全部楼层
这个是client的代码
  1. package main
  2. import (
  3.         "fmt"
  4.         "net"
  5.         //"net/http"
  6.         "time"
  7. )
  8. func main() {
  9.         //fmt.Println(http.ListenAndServe(":6060",nil))
  10.         con, err := net.Dial("tcp", "127.0.0.1:9876")
  11.         if err != nil {
  12.                 fmt.Println(err)
  13.                 return
  14.         }
  15.         //defer con.Close()
  16.         data := []byte("i love you")
  17.         nWrite,_ := con.Write(data[:])
  18.         fmt.Println((nWrite))

  19.         data1 := []byte("i love you 1")
  20.         nWrite1,_ := con.Write(data1[:])
  21.         fmt.Println((nWrite1))
  22.         time.Sleep(20*time.Second)
  23. }
复制代码
这个是server的代码
  1. package main
  2. import (
  3.         "fmt"
  4.         //"net/http"
  5.         "net"
  6. )
  7. func main() {
  8.         //fmt.Println(http.ListenAndServe(":6060",nil))
  9.         ln, err := net.Listen("tcp", "127.0.0.1:9876")
  10.         if err != nil {
  11.                 fmt.Println(err)
  12.                 return
  13.         }
  14.         defer ln.Close()
  15.         for {
  16.                 conn,err := ln.Accept()
  17.                 if err != nil {
  18.                         fmt.Println(err)
  19.                         continue
  20.                 }
  21.                 recv := make([]byte, 20)
  22.                 conn.Read(recv[:])
  23.                 fmt.Println(string(recv[:]))
  24.         }
  25. }
复制代码
启动运行的时候, 只能输出

i love you
10
12

没有预期的输出两次,请教这个问题的原因是? 以及如何解决呢?

论坛徽章:
0
发表于 2013-07-03 00:27 |显示全部楼层
本帖最后由 svenwang 于 2013-07-03 00:31 编辑

回复 3# z78290250

可以启动goroutine去处理新建立的连接,这样accept和连接的处理就不会相互等待了。注意goroutine结束的时候关闭连接,避免资源泄漏。

  1. package main
  2. import (
  3.         "fmt"        //"net/http"
  4.        "net"
  5. )
  6. func main() {
  7.        //fmt.Println(http.ListenAndServe(":6060",nil))
  8.        ln, err := net.Listen("tcp", "127.0.0.1:9876")
  9.        if err != nil {
  10.                fmt.Println(err)
  11.                return
  12.        }
  13.        defer ln.Close()
  14.        for {
  15.                  conn,err := ln.Accept()
  16.                 if err != nil {
  17.                         fmt.Println(err)
  18.                         continue
  19.                 }
  20.                 go func() {
  21.                         defer conn.Close()
  22.                         recv := make([]byte, 20)
  23.                         for {
  24.                                 n, err := conn.Read(recv[:])
  25.                                 if err != nil {
  26.                                         break
  27.                                 }
  28.                                 fmt.Println(string(recv[:n]))
  29.                         }
  30.                 }()
  31.         }
  32. }
复制代码

论坛徽章:
0
发表于 2013-07-01 18:15 |显示全部楼层
修改了一下,FYI
  1. package main

  2. import (
  3.         "fmt"
  4.         //"net/http"
  5.         "net"
  6. )

  7. func main() {
  8.         //fmt.Println(http.ListenAndServe(":6060",nil))
  9.         ln, err := net.Listen("tcp", "127.0.0.1:9876")
  10.         if err != nil {
  11.                 fmt.Println(err)
  12.                 return
  13.         }
  14.         conn, err := ln.Accept()
  15.         if err != nil {
  16.                 panic(err)

  17.         }
  18.         recv := make([]byte, 20)
  19.         defer ln.Close()
  20.         for {

  21.                 n, err := conn.Read(recv[0:])
  22.                 if n > 0 {
  23.                         fmt.Println(string(recv[0:n]))
  24.                 }

  25.                 if err != nil {
  26.                         fmt.Println(err)
  27.                         return
  28.                 }

  29.         }
  30. }
复制代码

论坛徽章:
0
发表于 2013-07-02 09:16 |显示全部楼层
回复 2# Kotokz


    嗯,昨天也试过这样修改,server端放在for循环里, 循环一次结束, con就关闭了, 但是放在外面之后,当关闭客户端的时候,server就读不到数据,就是eof,退出程序了, 还是想让他继续服务的。

论坛徽章:
0
发表于 2013-07-02 15:33 |显示全部楼层
oh, 那就试试下面的
  1. package main

  2. import (
  3.         "fmt"
  4.         //"net/http"
  5.         "net"
  6. )

  7. func main() {
  8.         //fmt.Println(http.ListenAndServe(":6060",nil))
  9.         ln, err := net.Listen("tcp", "127.0.0.1:9876")
  10.         if err != nil {
  11.                 fmt.Println(err)
  12.                 return
  13.         }
  14.         conn, err := ln.Accept()
  15.         if err != nil {
  16.                 panic(err)

  17.         }
  18.         recv := make([]byte, 20)
  19.         defer ln.Close()
  20.         for {

  21.                 n, err := conn.Read(recv[0:])
  22.                 if n > 0 {
  23.                         fmt.Println(string(recv[0:n]))
  24.                 }

  25.                 if err != nil {
  26.                         fmt.Println(err)
  27.                         conn, err = ln.Accept()
  28.                         if err != nil {
  29.                                 panic(err)

  30.                         }
  31.                 }

  32.         }
  33. }
复制代码

论坛徽章:
0
发表于 2013-07-03 09:47 |显示全部楼层
回复 5# svenwang


    这个可行,还是不太清楚这个原理,依然还是需要外面的那个循环来建立连接,是么?

论坛徽章:
0
发表于 2013-07-03 11:23 |显示全部楼层
回复 6# z78290250

你如果还想接收新的连接,就继续外面的那个Accept的循环。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

SACC2019中国系统架构师大会

【数字转型 架构演进】SACC2019中国系统架构师大会,8.5折限时优惠重磅来袭!
2019年10月31日~11月2日第11届中国系统架构师大会(SACC2019)将在北京隆重召开。四大主线并行的演讲模式,1个主会场、20个技术专场、超千人参与的会议规模,100+来自互联网、金融、制造业、电商等领域的嘉宾阵容,将为广大参会者提供一场最具价值的技术交流盛会。

限时8.5折扣期:2019年9月30日前


----------------------------------------

大会官网>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP