golang连接java的socket,golang socket编程

osi参考模型将计算机网络结构分为7个层次,但是在实际的开发应用中,我们更加认可TCP/IP族协议的五层结构,即应用层(http、ftp、dns),传输层(udp、tcp),网络层(ip),链路层(以太网),物理层。

socket编程作为一种基于网络层和传输层的数据io模式主要分为两种,TCP Socket和UDP Socket,也即面向连接的流式Socket和面向无连接的数据报式Socket。

今天主要和大家讲讲golang的TCP Socket编程。先来看个简单的例子吧

server.go

//模拟server端

func main() {

tcpServer, _ := net.ResolveTCPAddr("tcp4", ":8080")

listener, _ := net.ListenTCP("tcp", tcpServer)

for {

//当有新的客户端请求来的时候,拿到与客户端的连接

conn, err := listener.Accept()

if err != nil {

fmt.Println(err)

continue

}

//处理逻辑

go handle(conn)

}

}

func handle(conn net.Conn) {

defer conn.Close()

//读取客户端传送的消息

go func() {

response, _ := ioutil.ReadAll(conn)

fmt.Println(string(response))

}()

//向客户端发送消息

time.Sleep(1 * time.Second)

now := time.Now().String()

conn.Write([]byte(now))

}

client.go

//模拟客户端

func main() {

if len(os.Args) < 2 {

fmt.Fprintf(os.Stderr, "Usage: %s host:port", os.Args[0])

}

//获取命令行参数 socket地址

server := os.Args[1]

addr, err := net.ResolveTCPAddr("tcp4", server)

checkError(err)

//建立tcp连接

conn, err := net.DialTCP("tcp4", nil, addr)

checkError(err)

//向服务端发送数据

_, err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n"))

checkError(err)

//接收响应

response, _ := ioutil.ReadAll(conn)

fmt.Println(string(response))

os.Exit(0)

}

func checkError(err error) {

if err != nil {

fmt.Println(err)

os.Exit(1)

}

}

整体大概的流程是:

server端先通过tcp协议监听端口8080,之后当有客户端来访问时能够读取信息并且写入响应信息,注意此处 conn, err := listener.Accept() 语句是用来获取下一个调用连接的,如果一直没有连接,则会处于阻塞状态。

客户端通过DialTCP尝试与服务端建立连接,连接成功后向服务器端发送数据并接收响应,并且以上代码中,只有等待服务器端关闭连接之后,该连接才会失效,否则连接会一直处于ESTABLISHED状态。如下图是笔者将defer conn.Close()注释掉之后,查看的8080端口的连接,会发现连接一直存在:

75aa831f6d5ec1b84ffaf4a95a0c4773.png

如果使用细心一点的话,在客户端代码执行结束之后,此时的服务器端连接并没有释放(注意下图local address是8080端口),而是进入了TIME_WAIT状态:

edf4043b99ef4eda25afee65584ae843.png

一开始笔者以为是连接没有正确释放的原因,后来查看了下TCP四次挥手有关的内容才弄明白这块的原因,因为是服务器端主动断开连接,所以在服务器端发送完最后一个ACK之后,会进入TIME_WAIT状态等待一段时间,防止ACK没有发送成功,等待时间一过,系统会自动释放连接。如下是一个简单的状态转变图(不是特别精准,只看断开连接部分),希望能对读者有所帮助:

32adeaaac575afcafa311879591a5fe1.png

详细的四次挥手的各个状态轮转的变化,可以去谷歌搜索一下。

PS:以上是一个简单的socket编程的示例,只包含了一对client和server,那如果一个server有很多个client,此时有一个client希望能够将消息发送给除它自己之外的所有client fd怎么办?

其实这个问题可以通过server端来做,首先server端定义一种数据结构,无论是map还是slice,然后将所有的有效连接都放入其中,如果有client fd发送消息过来,遍历该结构,将消息发送给每一个非当前client的fd,由此解决该问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值