Go语言学习-网络基础

简介: Go语言学习-网络基础

前言


GO语言网络学习,网络的底层实现原理还是通过p网络的osix api实现,net 包是实现了对于网络接口的高级封装。此文章网络模块的学习主要是对于net 包中接口的练习。


一、网络模块学习


GO语言联系net包中TCP的协议实现客户端和服务端,客户端通过命令实现文件的上传和下载。


二、功能模块


1.客户端代码

思路: 客户端,上传文件,打开文件,读取数据,然后发送数据

客户端下载文件, 在网络中获取数据,然后写入文件;


代码如下(示例):

package main
import (
  "flag"
  "fmt"
  "io"
  "log"
  "net"
  "os"
  "path"
  "strings"
)
var (
  up       int
  fileName string
)
const SOURCE_DIR = "E:/GoSource/tcp-trans-file/tcp-trans-file/sourceFile/"
const DOWNLOAD_DIR = "E:/GoSource/tcp-trans-file/tcp-trans-file/download/"
// 实现命令行参数
func getComandArgs() {
  flag.IntVar(&up, "up", 1, "0 下载, 1 上传")
  flag.StringVar(&fileName, "f", "", "文件名称")
  flag.Parse()
}
func main() {
  log.SetFlags(log.Llongfile)
  getComandArgs()
  // 建立网络链接,监听localhsot:9090 端口
  conn, err := net.Dial("tcp", "localhost:9090")
  if err != nil {
    log.Println(err)
    return
  }
  defer conn.Close()
  // fileName 中路径中的window格式路径转换成linux 格式
  fileName = strings.ReplaceAll(fileName, "\\", "/")
  _, fileName = path.Split(fileName) // 分割术只识别”/“, 不能够识别”\“
  isUp := byte(1)
  if up != 1 {
    isUp = byte(0)
  }
  // 第一个包的格式 0:up/down 1Byte: filenamelen, 其它 filename
  fileInfoByte := make([]byte, 0, 1024) // 0 :len  1024 cap
  fileInfoByte = append(fileInfoByte, isUp, byte(len(fileName)))
  fileInfoByte = append(fileInfoByte, []byte(fileName)...)
  fileInfoByte = fileInfoByte[:1024]
  if _, err := conn.Write(fileInfoByte); err != nil {
    log.Println(err)
    return
  }
  if isUp == 1 {
    err := sendFile(conn, SOURCE_DIR+fileName)
    if err != nil {
      log.Println(err)
      return
    }
  } else {
    fmt.Printf("%s", DOWNLOAD_DIR+fileName)
    err := recvFile(conn, DOWNLOAD_DIR+fileName)
    if err != nil {
      log.Println(err)
      return
    }
  }
  //  fmt.Println(isUp)
  //  fmt.Println(fileInfoByte)
  /*
    data := make([]byte, 1024)
    copy(data, "hello server\n")
    number, err := conn.Write(data)
    if err != nil {
      fmt.Println(err)
      return
    }
    fmt.Println(number, err)
    data1 := make([]byte, 1024)
    n, err := conn.Read(data1)
    if err != nil {
      log.Println(err)
      return
    }
    fmt.Println(string(data1[:n]))
  */
}
func sendFile(conn net.Conn, filePath string) (err error) {
  src, err := os.Open(filePath)
  if err != nil {
    log.Println(err)
    return
  }
  defer src.Close()
  buf := make([]byte, 1024)
  n := 0
  for {
    n, err = src.Read(buf)
    if err != nil && err != io.EOF {
      log.Println(err)
      return
    } else {
      err = nil
    }
    if n == 0 {
      break
    }
    if _, err = conn.Write(buf[:n]); err != nil {
      log.Println(err)
      return
    }
  }
  return
}
func recvFile(conn net.Conn, filePath string) (err error) {
  file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY, 0644)
  if err != nil {
    log.Println(err)
    return
  }
  defer file.Close()
  buf := make([]byte, 1024)
  n := 0
  for {
    n, err = conn.Read(buf)
    if err != nil && err != io.EOF {
      log.Println(err)
      return
    } else {
      err = nil
    }
    if n == 0 {
      break
    }
    file.Write(buf)
  }
  return
}

2.服务端代码

代码如下(示例):

package main
import (
  "io"
  "log"
  "net"
  "os"
)
const OP_UPLOAD = 1
const OP_DOWNLOAD = 0
const UPLOAD_DIR = "E:/GoSource/tcp-trans-file/tcp-trans-file/upload/"
const SOURCE_DIR = "E:/GoSource/tcp-trans-file/tcp-trans-file/sourceFile/"
func main() {
  log.SetFlags(log.Llongfile)
  listener, err := net.Listen("tcp", ":9090")
  if err != nil {
    log.Println(err)
    return
  }
  defer listener.Close()
  log.Println("listen on:", listener.Addr().String())
  for {
    conn, err := listener.Accept()
    if err != nil {
      log.Println(err)
      return
    }
    log.Println("new conn:", conn.RemoteAddr())
    go handle(conn)
  }
}
func handle(conn net.Conn) {
  defer func() {
    recover()
    log.Println("close conn", conn.RemoteAddr())
    conn.Close()
  }()
  //文件的前1024个字节存放文件信息,  0: 上传还是下载
  fileInfoBytes := make([]byte, 1024)
  _, err := conn.Read(fileInfoBytes)
  if err != nil {
    log.Println(err)
    return
  }
  op := int(fileInfoBytes[0])
  fileNameLen := int(fileInfoBytes[1])
  fileName := string(fileInfoBytes[2 : fileNameLen+2])
  if op == OP_UPLOAD {
    err := receFile(conn, UPLOAD_DIR+fileName)
    if err != nil {
      log.Println(err)
      return
    }
  } else if op == OP_DOWNLOAD {
    err := sendFile(conn, SOURCE_DIR+fileName)
    if err != nil {
      log.Println(err)
      return
    }
  }
  /*
    fmt.Println(string(data[:n]))
    n, err = conn.Write([]byte("recv:" + string(data[:n])))
    if err != nil {
      log.Println(err)
      return
    }
  */
}
func receFile(conn net.Conn, filePath string) (err error) {
  file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY, 0644)
  //file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY, 0644)
  if err != nil {
    log.Println(err)
    return
  }
  defer file.Close()
  buf := make([]byte, 1024)
  n := 0
  for {
    n, err = conn.Read(buf)
    if err != nil && err != io.EOF {
      log.Println(err)
      return
    } else {
      err = nil
    }
    if n == 0 {
      break
    }
    file.Write(buf)
  }
  return
}
func sendFile(conn net.Conn, filePath string) (err error) {
  src, err := os.Open(filePath)
  if err != nil {
    log.Println(err)
    return
  }
  defer src.Close()
  buf := make([]byte, 1024)
  n := 0
  for {
    n, err = src.Read(buf)
    if err != nil && err != io.EOF {
      log.Println(err)
      return
    } else {
      err = nil
    }
    if n == 0 {
      break
    }
    if _, err = conn.Write(buf[:n]); err != nil {
      log.Println(err)
      return
    }
  }
  return
}

总结


在网络模块的联系中,一定要注意语言的特性,使用双引号一定要是英文的,避免中文格式。

目录
相关文章
|
3天前
|
JavaScript Java Go
探索Go语言在微服务架构中的优势
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出。本文将深入探讨Go语言在构建微服务时的性能优势,包括其在内存管理、网络编程、并发模型以及工具链支持方面的特点。通过对比其他流行语言,我们将揭示Go语言如何成为微服务架构中的一股清流。
|
1天前
|
数据采集 监控 Java
go语言编程学习
【11月更文挑战第3天】
14 7
|
2天前
|
Ubuntu 编译器 Linux
go语言中SQLite3驱动安装
【11月更文挑战第2天】
16 7
|
8天前
|
网络协议 安全 Go
Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
【10月更文挑战第28天】Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
34 13
|
2天前
|
关系型数据库 Go 网络安全
go语言中PostgreSQL驱动安装
【11月更文挑战第2天】
18 5
|
2天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
13 4
|
3天前
|
SQL 关系型数据库 MySQL
go语言中安装数据库驱动
【11月更文挑战第1天】
16 5
|
2天前
|
存储 设计模式 安全
Go语言中的并发编程:从入门到精通###
本文深入探讨了Go语言中并发编程的核心概念与实践技巧,旨在帮助读者从理论到实战全面掌握Go的并发机制。不同于传统的技术文章摘要,本部分将通过一系列生动的案例和代码示例,直观展示Go语言如何优雅地处理并发任务,提升程序性能与响应速度。无论你是Go语言初学者还是有一定经验的开发者,都能在本文中找到实用的知识与灵感。 ###
|
3天前
|
编译器 Go 开发者
go语言中导入相关包
【11月更文挑战第1天】
13 3
|
4天前
|
测试技术 Go
go语言中测试工具
【10月更文挑战第22天】
14 4
下一篇
无影云桌面