zoukankan      html  css  js  c++  java
  • golang socket编程,实现http协议

    https://studygolang.com/articles/11796

     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
    Content-Type:text/html
    Content-Length:3
    
    aaa"))
       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
    
    "))
            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端口的连接,会发现连接一直存在:

  • 相关阅读:
    XLS导出的服务器端配置方式
    SQLSERVER2008 内存占用高的处理方式
    word定义多级列表
    SQL Server替换特殊字符
    php和mysql两种不同方式的分割字符串和类型转换
    tp杂记
    MySql数据库 主从复制/共享 报错
    the server ssl certificate failed to verify
    loaded some nib but the view outlet was not set(转载)
    xcode7 调用相册权限无提示
  • 原文地址:https://www.cnblogs.com/oxspirt/p/13269249.html
Copyright © 2011-2022 走看看