Go语言socket网络编程(一)

Go语言socket网络编程(一)

一、IP查找与转换

1、获取ip与电脑信息的函数信息

	str := net.JoinHostPort("127.0.0.1", "8080")
	str1 := net.JoinHostPort("::1", "8080")              //端口,IP合并
	host, port, _ := net.SplitHostPort("127.0.0.1:8080") //端口,IP分离
	Name, _ := net.LookupAddr("127.0.0.1")               //查询主机名
	addr, _ := net.LookupAddr("61.135.169.121")          //查询域名,返回的是切片
	fmt.Println(net.LookupHost("www.baidu.com"))
	log.Println(str)  //str
	log.Println(str1) //str
	log.Println(host) //str
	log.Println(port) //str
	log.Println(Name) //str
	log.Println(addr) //str

2、有些库必须使用IP格式,所以需要返回IP形式

	ip := net.ParseIP("127.0.0.1") //通过字符串转换为IP地址
	fmt.Printf("%T,%v", ip, ip)
	addrs, _ := net.LookupIP("www.baidu.com") //通过域名找IP
	log.Println(addrs)

3、判断IP地址是否在同一网段

ip, ipnet, _ := net.ParseCIDR("192.168.10.110/24")
	log.Println(ip)
	log.Println(ipnet)
	newIp := net.ParseIP("192.168.12.12")
	bool := ipnet.Contains(newIp)
	log.Println(bool)

4、获取主机相关连接

package main

import (
	"fmt"
	_ "fmt"
	"net"
)

func main() {
     
	addrs, _ := net.InterfaceAddrs() //获取当前机器的网络名,字符串格式的IP地址
	for _, addr := range addrs {
     
		fmt.Println(addr.Network(), addr.String())
	}
}

5、获取系统网络接口

func main() {
     
	ifc, _ := net.Interfaces()
	for _, v := range ifc {
     
		fmt.Println(v)
	}
}

二、TCP连接

1、交互聊天

(1)服务器

package main

import (
	"bufio"
	"fmt"
	"log"
	"net"
	"os"
)

func main() {
     
	log.SetPrefix("main")
	file, err := os.OpenFile("Server.log", os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.ModePerm)
	defer file.Close()
	if err != nil {
     
		log.Fatal("OpenFile:", err)
	}
	log.SetOutput(file)
	listen, err := net.Listen("tcp", "127.0.0.1:8888")
	if err != nil {
     
		log.Println(err)
	}
	conn, err := listen.Accept()
	if err != nil {
     
		log.Println("Accept", err)
	}
	defer conn.Close()
	for {
     
		data := make([]byte, 1024)
		reader := bufio.NewReader(conn)
		n, err := reader.Read(data)
		if err != nil {
     
			log.Println("buf", err)
			break
		}
		fmt.Println(string(data[0:n]))
	}
}

(2)客户端

package main

import (
	"bufio"
	"fmt"
	"log"
	"net"
	"os"
)

func main() {
     
	log.SetPrefix("client")
	file, err := os.OpenFile("Client.log", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0777)
	if err != nil {
     
		log.Fatal(err)
	}
	log.SetOutput(file)
	conn, err := net.Dial("tcp", "127.0.0.1:8888")
	defer conn.Close()
	if err != nil {
     
		log.Println("Dial", err)
	}
	scan := bufio.NewScanner(os.Stdin)
	fmt.Println("请输入你要发送的消息:")
	scan.Scan() //扫描
	fmt.Fprint(conn, scan.Text())
}

2、服务器文件指令实现

三、UDP连接

1、Server端聊天

package main

import (
	"fmt"
	"log"
	"net"
	"os"
)

func main() {
     
	file, err := os.Create("ServerLog.log")
	log.SetPrefix("server:")
	if err != nil {
     
		log.Fatal(err)
	}
	log.SetOutput(file)
	addr := "127.0.0.1:8080"
	packetConn, err := net.ListenPacket("udp", addr) //使用UDP的方式监听
	defer packetConn.Close()
	if err != nil {
     
		log.Println(err)
	}
	ctx := make([]byte, 1024)
	for {
     
		n, addr, err := packetConn.ReadFrom(ctx)
		if err != nil {
     
			log.Println(err)
		}
		fmt.Println(addr.String()) //传输过来的地址
		fmt.Println(string(ctx[0:n]))
		packetConn.WriteTo([]byte("测试UDP传输回去"), addr)
	}
}

2、客户端聊天

package main

import (
	"fmt"
	"log"
	"net"
	"os"
)

func main() {
     
	var str string
	file, err := os.Create("ClientErr.log")
	if err != nil {
     
		log.Fatal(err)
	}
	log.SetOutput(file)
	conn, err := net.Dial("udp", "127.0.0.1:8080")
	if err != nil {
     
		log.Println(err)
	}
	fmt.Scanln(&str)
	fmt.Fprintf(conn, "%s", str)
	ctx := make([]byte, 1024)
	n, err := conn.Read(ctx)
	if err != nil {
     
		log.Println(err)
	}
	fmt.Println(string(ctx[0:n]))
}

四、HTTP协议

1、简单的web服务三步骤

package main

import (
	"fmt"
	"net/http"
	"time"
)

//Http的三步骤
//1、处理器函数
//2、绑定URL关系
//3、启动Server服务
func main() {
     
	//处理器函数
	timeFunc := func(response http.ResponseWriter, request *http.Request) {
     
		fmt.Println(request)
		now := time.Now().Format("2006-01-02 15:04:05")
		fmt.Fprint(response, now)
	}
	//绑定URL关系
	http.HandleFunc("/home/", timeFunc) //第一个参数为路径,第二个参数为匿名函数
	//启动web服务
	http.ListenAndServe(":9999", nil)
}

2、三部曲读取文件内容

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
)

//Http的三步骤
//1、处理器函数
//2、绑定URL关系
//3、启动Server服务
func main() {
     
	http.HandleFunc("/", func(response http.ResponseWriter, request *http.Request) {
     
		ctx, err := ioutil.ReadFile("HTTP/index.html")
		if err != nil {
     
			fmt.Fprintf(response, "%s", "网页读取出现错误")
			fmt.Println(err)
			fmt.Println(string(ctx))
		} else {
     
			fmt.Fprintf(response, "%s", string(ctx))
		}
	})
	http.ListenAndServe("127.0.0.1:9999", nil)
}

3、面向对象实现

package main

import (
	"fmt"
	"net/http"
	"time"
)

//使用对象接口的思维来维护
type TimeHandler struct {
     
} //定义结构体来实现接口
func (h *TimeHandler) ServeHTTP(response http.ResponseWriter, request *http.Request) {
     
	now := time.Now().Format("2006-01-02 15:04:05")
	fmt.Fprint(response, now)
}

func main() {
     
	http.Handle("/time/", &TimeHandler{
     }) //传入实现结构的方法
	http.ListenAndServe("127.0.0.1:9999", nil)
}

4、获取报文信息

package main

import (
	"fmt"
	"net/http"
)

func main() {
     
	http.HandleFunc("/", func(resp http.ResponseWriter, req *http.Request) {
     
		fmt.Println(req.Method, req.URL, req.Proto)
		fmt.Println(req.Header) //获取请求头的信息
		fmt.Println(req.Header.Get("User-Agent"))
	})
	http.ListenAndServe("127.0.0.1:9999", nil)
}

5、参数解析

(1) Post参数解析

package main

import (
	"fmt"
	"net/http"
)

//解析参数
//http协议
//post获取数据

func main() {
     
	http.HandleFunc("/", func(resp http.ResponseWriter, req *http.Request) {
     
		fmt.Println(req.PostFormValue("a")) //获取post的a值
		req.ParseForm()
		fmt.Println(req.PostForm) //只包含请求体数据
	})
	http.ListenAndServe("127.0.0.1:9999", nil)
}

(2)Get参数解析

package main

import (
	"fmt"
	"net/http"
)

//解析参数
//http协议
//post获取数据

func main() {
     
	http.HandleFunc("/", func(resp http.ResponseWriter, req *http.Request) {
     
		req.ParseForm()
		fmt.Println(req.Form)
		fmt.Println(req.Form.Get("a"))  //获取a的值
		fmt.Println(req.Form["a"])      //获取a的值
		fmt.Println(req.FormValue("a")) //获取a的值
		fmt.Println(req.PostForm)       //只包含请求体数据
	})
	http.ListenAndServe("127.0.0.1:9999", nil)
}

(3)上传文件,获取文件相关信息

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

//上传文件 =>multipart/form-data

func main() {
     
	http.HandleFunc("/", func(resp http.ResponseWriter, req *http.Request) {
     
		//第一种方式
		//req.ParseMultipartForm(1024 * 1024) //解析提交内容
		//fmt.Println(req.MultipartForm)
		//file, err := req.MultipartForm.File["a"][0].Open()
		//if err != nil {
     
		//	fmt.Println(err)
		//}
		//io.Copy(os.Stdout, file)
		//第二种方式
		file, header, _ := req.FormFile("a")
		fmt.Println(header.Filename) //文件名
		fmt.Println(header.Size)     //文件大小
		fmt.Println(header.Header)   //文件头的相关信息
		io.Copy(os.Stdout, file)
	})
	http.ListenAndServe("127.0.0.1:8888", nil)
}

6、json格式获取

package main

import (
	"encoding/json"
	"fmt"
	"net/http"
)

//上传文件 =>multipart/form-data

func main() {
     
	http.HandleFunc("/", func(resp http.ResponseWriter, req *http.Request) {
     
		//io.Copy(os.Stdout, req.Body) //读取请求头的数据,流只能解析一次
		decoder := json.NewDecoder(req.Body) //解析流
		var info map[string]interface{
     }
		decoder.Decode(&info) //将解析的coder对象放在map中(里面可以放任意接口)
		fmt.Println(info)
		fmt.Println(info["a"])
	})
	http.ListenAndServe("127.0.0.1:8888", nil)
}

7、Cookie

package main

import (
	"net/http"
	"strconv"
	"strings"
)

func SetCook(cookie string) map[string]string {
     
	cookieMap := make(map[string]string)
	vals := strings.Split(cookie, ";") //切分cookie
	for _, val := range vals {
     
		cook := strings.Split(val, "=") //将cookie分为map类型
		cookieMap[strings.TrimSpace(cook[0])] = strings.TrimSpace(cook[1])
	}
	return cookieMap
}

//上传文件 =>multipart/form-data
func main() {
     
	http.HandleFunc("/", func(resp http.ResponseWriter, req *http.Request) {
     
		cookieMap := SetCook(req.Header.Get("cookie")) //处理cookie函数
		counter := 0
		if v, err := strconv.Atoi(cookieMap["counter"]); err == nil {
     
			counter = v
		}
		counterCookie := &http.Cookie{
     
			Name:     "counter",
			Value:    strconv.Itoa(counter + 1),
			HttpOnly: true,
		} //当访问这个网页的时候,服务器返回一个cookie回去
		http.SetCookie(resp, counterCookie) //将cookie的值使用响应体的方式返回
	})
	http.ListenAndServe("127.0.0.1:9999", nil)
}


8、重镜像

package main

import (
	"fmt"
	"net/http"
)

func main() {
     
	http.HandleFunc("/home/", func(resp http.ResponseWriter, req *http.Request) {
     
		//fmt.Fprint(resp, "首页")//当前页面
		//进行重镜像
		http.Redirect(resp, req, "/Login/", 302) //将网址重定向到login中
	})
	http.HandleFunc("/Login/", func(resp http.ResponseWriter, req *http.Request) {
     
		fmt.Fprint(resp, "登录")
	})
	http.ListenAndServe("127.0.0.1:9999", nil)
}

9、文件服务器(类似Nginx)

package main

import (
	"net/http"
)

func main() {
     
	http.Handle("/static/", http.FileServer(http.Dir("./")))
	//第一种
	http.Handle("/static2/", http.StripPrefix("/static2/", http.FileServer(http.Dir("./www"))))
	//第二种
	http.Handle("/www/", http.FileServer(http.Dir(".")))
	http.ListenAndServe("127.0.0.1:9999", nil)
}

10、发送请求

package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
)

//发送相关请求
func main() {
     
	//通过Get发送请求
	response, err := http.Get("http://localhost:9999/?a=1&b=2")
	if err != nil {
     
		fmt.Println(err)
	} else {
     
		//fmt.Println(response.Proto, response.StatusCode, response.Status)
		//fmt.Println(response.Header)
		io.Copy(os.Stdout, response.Body)
	}
	//通过post发送请求
	buf := bytes.NewBufferString(`{"name":12}`) //创建一个缓冲对象
	resp, err := http.Post("localhost:9999", "application/json", buf)
	fmt.Println(resp, err)
	//通过PostForm请求
	parms := url.Values{
     }    //创建map映射
	parms.Add("name", "tom") //添加映射
	resp, err := http.PostForm("http://localhost:8888", parms)
	fmt.Println(resp, err)
}

你可能感兴趣的:(Go语言网络编程)