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\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端口的連接,會發現連接一直存在:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM