1.网络编程基本介绍

Golang的主要设计目标之一就是面向大规模后端服务程序,网络通信这块是服务端程序必不可少也是至关重要的一部分

网络编程有两种:

1)TCP socket编程,是网络编程的主流。底层是基于TCP/IP协议的,例如QQ等客户端。

2)b/s结构(Browser/Server,浏览器/服务器模式)的是http编程,使用浏览器访问服务器时,使用的是http协议,而http底层依旧是用tcp socket实现的。比如京东

2.快速入门

服务器端的处理流程

1)监听端口【8888】

2)接收客户端的tcp链接,建立客户端和服务端的链接

3)创建foroutine,处理该链接的请求(通常客户端会通过链接发送请求包)

客户端的处理流程

1)建立与服务端的链接

2)发送请求数据【终端】,接收服务器端返回的结果数据

3)关闭链接

使用net包进行网络编程

package net :import "net"

net包提供了可移植的网络I/O接口,包括TCP/IP、UDP、域名解析和Unix域socket。

虽然本包提供了对网络原语的访问,大部分使用者只需要Dial、Listen和Accept函数提供的基本接口;以及相关的Conn和Listener接口。crypto/tls包提供了相同的接口和类似的Dial和Listen函数。

Listen函数创建的服务端:

ln, err := net.Listen("tcp", ":8080")
if err != nil {
	// handle error
}
for {
	conn, err := ln.Accept()
	if err != nil {
		// handle error
		continue
	}
	go handleConnection(conn)
}

Dial函数使客户端和服务端建立连接:

conn, err := net.Dial("tcp", "google.com:80")
if err != nil {
	// handle error
}
fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n")
status, err := bufio.NewReader(conn).ReadString('\n')
// ...

案例
写一个客户端和服务端,使客户端发送消息给客户端,输入一行发送一行,在客户端输入exit退出
server.go
package main

import (
    "fmt"
    "io"
    "net"
)

func process(conn net.Conn) {
    defer conn.Close()
    for {
        buf := make([]byte, 1024)
        //1.等待客户端write数据给conn
        //2.如果客户端没有发送数据,则堵塞在这里
        //fmt.Printf("服务器在等待客户端%s,发送消息\n", conn.RemoteAddr().String())
        n, err := conn.Read(buf) //从conn读取
        if err == io.EOF {
            fmt.Printf("客户端文件读取完毕退出\n")
            return
        }
        //3.显示客户端发送的数据,将切片强制转换为string并截取buf的前n个数据
        fmt.Printf(string(buf[:n]))
    }
}

func main() {
    listen, err := net.Listen("tcp", "0.0.0.0:8888")
    if err != nil {
        fmt.Printf("listen错误%v\n", err)
        return
    }
    defer listen.Close() //延时关闭listen
    //循环等待客户链接listen.Accept
    for {
        fmt.Println("等待有客户来链接...")
        conn, err := listen.Accept()
        if err != nil {
            fmt.Printf("conn接收错误err=%v\n", err)
        } else {
            fmt.Printf("接收成功,conn:%v,客户端ip为%v\n", conn, conn.RemoteAddr().String())
        }
        go process(conn)
    }

}

client.go

package main

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

func main() {
    conn, err := net.Dial("tcp", "10.11.16.177:8888")
    if err != nil {
        fmt.Printf("服务器链接错误:%v\n", err)
        return
    }
    fmt.Printf("链接服务器成功:%v\n", conn)
    //功能一.客户端可以发送单行数据,然后退出
    //1.新建bufio.NewReader 从标准输入os.Stdin接收数据 给reader
    reader := bufio.NewReader(os.Stdin)
    for {
        //2.reader 读取数据直到碰到换行符'\n'
        line, err := reader.ReadString('\n')
        if err != nil {
            fmt.Printf("writer.ReadString错误:%v\n", err)
        }
        //将line的换行符"\n"去掉
        line = strings.Trim(line, "\n")
        //输入exit为退出
        if line == "exit" {
            fmt.Println("退出写入")
            break
        }
        //3.将读到的数据line传送给服务器
        //给line加上换行符
        _, err1 := conn.Write([]byte(line + "\n"))
        if err1 != nil {
            fmt.Printf("conn.Write错误:%v\n", err1)
        }
    }
    //fmt.Printf("客户端发送了%v字节的数据,并退出\n", n)
}

3.海量用户即时通讯