好好爱自己!

golang socket编程,实现http协议

https://studygolang.com/articles/11796

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package main
 
import (
  "log"
  "net"
)
 
func handleConnection(conn net.Conn) error {
  defer conn.Close()
  var request = make([]byte, 1000)
  _, err := conn.Read(request)
  if err != nil {
    log.Println("failed to read request contents")
    return err
  }
  log.Printf("%#v", request)
  log.Println(string(request))
  _, err = conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Type:text/html\r\nContent-Length:3\r\n\r\naaa"))
  if err != nil {
    log.Println("failed to write response contents")
    return err
  }
  conn.Close()
  return nil
}
 
func main() {
  ln, err := net.Listen("tcp", "0.0.0.0:8081")
  if err != nil {
    panic("error listening on port 8080")
  }
  for {
    conn, err := ln.Accept()
    log.Println("received connection")
    if err != nil {
      panic("failed to accept connection")
    }
    handleConnection(conn)
  }
}

  

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

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端口的连接,会发现连接一直存在:

posted @   立志做一个好的程序员  阅读(2127)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现

不断学习创作,与自己快乐相处

点击右上角即可分享
微信分享提示