golang socket编程,实现http协议

摘要:
socket编程作为一种基于网络层和传输层的数据io模式主要分为两种,TCPSocket和UDPSocket,也即面向连接的流式Socket和面向无连接的数据报式Socket。今天主要和大家讲讲golang的TCPSocket编程。=nil{fmt.Printlncontinue}//处理逻辑gohandle}}funchandle{deferconn.Close()//读取客户端传送的消息gofunc(){response,_:=ioutil.ReadAllfmt.Println}()//向客户端发送消息time.Sleepnow:=time.Now().String()conn.Write}client.go//模拟客户端funcmain(){iflen˂2{fmt.Fprintf}//获取命令行参数socket地址server:=os.Args[1]addr,err:=net.ResolveTCPAddrcheckError//建立tcp连接conn,err:=net.DialTCPcheckError//向服务端发送数据_,err=conn.WritecheckError//接收响应response,_:=ioutil.ReadAllfmt.Printlnos.Exit}funccheckError{iferr!

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

golang socket编程,实现http协议第1张

免责声明:文章转载自《golang socket编程,实现http协议》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇C#解压、压缩RAR文件MySQL十进制转化为二进制、八进制、十六进制下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

golang解析json配置文件

安装 go get github.com/akkuman/parseConfig 使用说明 环境假设 . ├── config.go ├── config.json config.json内容 { "name" : "akkuman", "urls" : ["xx.com","ww.com"], "info" : {...

ZeroMQ接口函数之 :zmq_setsockopt –设置ZMQ socket的属性

ZeroMQ API 目录 :http://www.cnblogs.com/fengbohello/p/4230135.html 本文地址 :http://www.cnblogs.com/fengbohello/p/4398953.html 翻译:郝峰波 mail : fengbohello@qq.com ZeroMQ 官方地址 :http://api....

Failed to close server connection after message failures; nested exception is javax.mail.MessagingException: Can't send command to SMTP host

org.springframework.mail.MailSendException: Failed to close server connection after message failures; nested exception is javax.mail.MessagingException: Can't send command to SMTP...

Golang的time.NewTicker周期性定时器使用案例

 Ticker是一个周期触发定时的计时器,它会按照一个时间间隔往channel发送系统当前时间,而channel的接收者可以以固定的时间间隔从channel中读取事件。 一.通过NewTicker函数定义定时器 package main import ( "fmt" "time" ) func main() { //创建...

android黑科技系列——手机端破解神器MT的内购VIP功能破解教程

一、前言 在破解app的时候,我们现在几乎都是在PC端进行操作,但是之前bin神的MT管理器,可以在手机端直接破解,不过也有很大的局限性,但是对于一些简单的app破解没问题的。这个工具其实原理也很简单,就是解析apk中的dex,arsc等文件,然后支持修改其中的类方法信息和资源信息,然后在二次打包签名即可。其实把这部分功能移到了移动端做了,不过值得佩服的是...

golang-指针,函数,map

指针普通类型变量存的就是值,也叫值类型。指针类型存的是地址,即指针的值是一个变量的地址。一个指针只是值所保存的位置,不是所有的值都有地址,但是所有的变量都有。使用指针可以在无需知道变量名字的情况下,间接读取或更新变量的值。 获取变量的地址,用&,例如:var a int 获取a的地址:&a,&a(a的地址)这个表达式获取一个指向整型...