GO:Socket编程
目录
一、TCP/IP协议族和四层模型概述
1.1 互联网协议族(TCP/IP)
1.2 TCP/IP四层模型
1. 网络访问层(Network Access Layer)
2. 网络层(Internet Layer)
3. 传输层(Transport Layer)
4. 应用层(Application Layer)
1.3 特点和作用
二、Socket基础
2.1 Socket简介
2.2 TCP编程
2.2.1 TCP简介
2.2.2 TCP的关键特性
2.2.3 TCP客户端
2.2.4 TCP服务端
2.3 UDP编程
2.3.1 UDP简介
2.3.2 UDP客户端
2.3.3 UDP服务端
在学习 Socket之前,我们需要了解、什么是TCP/IP以及如何使用TCP/IP中的Socket 连接实现网络通信。Socket是我们在使用Go语言的过程中会使用到的最底层的网络协议,大部分的网络通信协议都是基于TCP/IP的Socket协议
一、TCP/IP协议族和四层模型概述
1.1 互联网协议族(TCP/IP)
- 是互联网的基础通信架构
- 包含整个网络传输协议家族
- 核心协议:TCP(传输控制协议)和IP(网际互连协议)
- 提供点对点的链接机制,标准化数据封装、定址、传输、路由和接收
1.2 TCP/IP四层模型
1. 网络访问层(Network Access Layer)
- 未详细描述,指出主机必须使用某种协议与网络相连
2. 网络层(Internet Layer)
- 关键部分,使用IP协议
- 功能:使主机可以发送分组到任何网络
- 特点:分组可能经由不同网络,到达顺序可能不同
3. 传输层(Transport Layer)
- 定义两个端到端协议:TCP和UDP
- TCP:面向连接,提供可靠传输、流量控制、多路复用等
- UDP:无连接,不可靠传输,用于简单应用
4. 应用层(Application Layer)
- 包含所有高层协议
- 主要协议:
- TELNET(远程终端)
- FTP(文件传输)
- SMTP(电子邮件)
- DNS(域名服务)
- HTTP(超文本传输)
- ...
1.3 特点和作用
- 将软件通信过程抽象为四个层
- 采用协议堆栈方式实现不同通信协议
- 简化了OSI七层模型
- 提供了灵活、可扩展的网络通信框架
二、Socket基础
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个 Socket。建立网络通信连接至少要一对端口号(Socket)。Socket的本质是编程接口(API),对 TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口。如果 说HTTP是轿车,提供了封装或者显示数据的具体形式,那么Socket就是发动机,提供了网络通信 的能力。
2.1 Socket简介
Socket的英文原义是“孔”或“插座”,作为BSD UNIX的进程通信机制,取后一种意思。 Socket通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不 同虚拟机或不同计算机之间的通信。在网络上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。
Socket正 如其英文原义那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座都有一个编 号,有的插座提供220伏交流电,有的提供110伏交流电,有的则提供有线电视节目。客户软件将 插头插到不同编号的插座中,就可以得到不同的服务。
Socket起源于Unix,而Unix的基本哲学之一就是“一切皆文件”,都可以使用如下模式来 操作。
打开 -> 读写write/read -> 关闭close
Socket就是该模式的一个实现,网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件 描述符。Socket的类型有两种:流式Socket和数据报式Socket。流式是一种面向连接的Socket,针 对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用
2.2 TCP编程
2.2.1 TCP简介
TCP是Transmission Control Protocol的缩写,中文名是传输控制协议。它是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中, 它完成第四层传输层所指定的功能,用户数据报协议(UDP)是同一层内另一个重要的传输协议。
在互联网协议族中,TCP层是位于IP层之上、应用层之下的中间层。不同主机的应用层之间经常需 要可靠的、像通道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。
TCP是因特网中的传输层协议,使用三次握手协议建立连接。当主动方发出SYN连接请求后, 等待对方回答SYN+ACK,并最终对对方的SYN执行ACK确认。这种建立连接的方法可以防止产生错误的连接。TCP使用的流量控制协议是可变大小的滑动窗口协议。TCP三次握手的过程如下:
这张图描述的是TCP(传输控制协议)的三次握手过程,这是建立TCP连接的标准方法。
1. 第一步 - SYN:
- 客户端发送一个SYN(同步)包到服务器。
- SYN=1 表示这是一个同步请求。
- seq=J 是客户端选择的初始序列号。
2. 第二步 - SYN-ACK:
- 服务器收到SYN后,回复一个SYN-ACK包。
- SYN=1 表示这也是一个同步包。
- ACK=1 表示这是一个确认包。
- ack=J+1 是对客户端序列号的确认(下一个期望收到的序列号)。
- seq=K 是服务器选择的初始序列号。
3. 第三步 - ACK:
- 客户端收到SYN-ACK后,发送一个ACK包作为响应。
- ACK=1 表示这是一个确认包。
- ack=K+1 是对服务器序列号的确认。
4. 连接建立:
- 完成这三步后,TCP连接就建立了。
- 双方都标记连接为ESTABLISHED状态。
这个过程的目的是:
- 同步双方的初始序列号。
- 确保双方都能发送和接收数据。
- 避免旧的或重复的连接干扰新连接。
这种机制保证了连接的可靠性和数据传输的有序性,是TCP协议可靠传输特性的基础。
2.2.2 TCP的关键特性
- 分段传输: 数据被分割成适合的数据块。
- 确认机制:
- 发送方启动定时器等待确认
- 接收方发送确认
- 校验和: 检测传输中的数据变化。
- 排序重组: 处理失序到达的数据包。
- 去重: 丢弃重复的数据包。
- 流量控制: 防止缓冲区溢出。
- 可靠传输: 通过以上机制确保数据可靠传输。
2.2.3 TCP客户端
Go语言提供了net包来实现Socket编程,大部分使用者只需要Dial、Listen和Accept函数提供的基本接口,以及相关的Conn和Listener接口。
对于网络编程而言,推荐使用log包代替fmt包进行打印信息,log包打印时,会附加打印出 时间,方便调试程序。log.Fatal表示当遇到严重错误时打印错误信息,并停止程序的运行。
对于TCP和UDP网络,地址格式是“host:port”或“[host]:port”,例如:
package mainimport ("log""net"
)func main() {// 尝试连接百度服务器conn, err := net.Dial("tcp", "www.baidu.com:80")// 连接本地端口// conn, err := net.Dial("tcp", ":1234")if err != nil {log.Fatal("连接失败!", err)}defer conn.Close()log.Println("连接成功!")
}
开启了一个对百度服务器的80端口的TCP连接,如果没报错,就表示连接成功,程序运行后输出如下:
2024/07/19 00:10:13 连接成功!
Dial函数在连接时,如果端口未开放,尝试连接就会立刻返回服务器拒绝连接的错误。
尝试连接本地(127.0.0.1)的1234端口,由于该端口未开放任何TCP服务,程序就会抛出连接失败的信息,如下所示:
2024/07/19 00:12:49 连接失败!dial tcp :1234: connectex: No connection could be made because the target machine actively refused it.
有时我们会遇到这种情况:需要连接的TCP服务开放着,但由于网络或者防火墙的原因,导致始终无法连接成功。这时我们需要设置超时时间来避免程序一直阻塞运行,设置超时可以使用 DialTimeout函数。
HTTP协议页是基于TCP的Socket协议实现的,因此可以使用TCP客户端来请求百度的HTTP服务。
package mainimport ("log""net"
)func main() {// 尝试连接百度服务器conn, err := net.Dial("tcp", "www.baidu.com:80")if err != nil {log.Fatal("连接失败!", err)}defer conn.Close()log.Println("连接成功!")// 发送HTTP形式的内容conn.Write([]byte("GET / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: curl/7.55.1\r\nAccept: */*\r\n\r\n"))log.Println("发送HTTP请求成功!")var buf = make([]byte, 1024)conn.Read(buf)log.Println(string(buf))
}
连接百度服务器的80端口,并向80端口发送了HTTP请求包,模拟了一次HTTP请求,百度服务器接收到并成功解析该请求后,就会做出响应,程序运行结果如下:
2024/07/19 00:59:26 连接成功!
2024/07/19 00:59:26 发送HTTP请求成功!
2024/07/19 00:59:27 HTTP/1.1 200 OK
Accept-Ranges: bytes
...
Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link
...
2.2.4 TCP服务端
- 将服务器代码保存为
server.go
,客户端代码保存为client.go
。 - 在一个终端中运行服务器,在另一个终端中运行客户端
- 在客户端终端中输入消息并按回车发送。你会看到服务器的响应。
- 你可以运行多个客户端实例来测试多客户端场景。
服务端
// 服务器代码 (server.go)
package mainimport ("bufio""fmt""net""time"
)func main() {// 在8080端口上创建TCP监听器listener, err := net.Listen("tcp", ":8080")if err != nil {fmt.Println("监听错误:", err)return}defer listener.Close() // 确保在函数结束时关闭监听器fmt.Println("服务器正在监听8080端口")for {// 接受新的客户端连接conn, err := listener.Accept()if err != nil {fmt.Println("接受连接错误:", err)continue}fmt.Println("新客户端连接:", conn.RemoteAddr())// 为每个客户端启动一个新的goroutine来处理连接go handleConnection(conn)}
}func handleConnection(conn net.Conn) {defer conn.Close() // 确保在函数结束时关闭连接reader := bufio.NewReader(conn)for {// 设置30秒的读取超时conn.SetReadDeadline(time.Now().Add(30 * time.Second))// 读取客户端发送的消息,直到遇到换行符message, err := reader.ReadString('\n')if err != nil {if netErr, ok := err.(net.Error); ok && netErr.Timeout() {fmt.Println("读取超时,关闭连接")} else {fmt.Println("读取错误:", err)}return}fmt.Printf("收到来自 %s 的消息: %s", conn.RemoteAddr(), message)// 设置10秒的写入超时conn.SetWriteDeadline(time.Now().Add(10 * time.Second))// 向客户端发送确认消息_, err = conn.Write([]byte("已接收: " + message))if err != nil {fmt.Println("写入错误:", err)return}}
}
客户端
// 客户端代码 (client.go)
package mainimport ("bufio""fmt""net""os""time"
)func main() {// 连接到服务器conn, err := net.Dial("tcp", "localhost:8080")if err != nil {fmt.Println("连接错误:", err)return}defer conn.Close() // 确保在函数结束时关闭连接fmt.Println("连接成功,请输入消息,按回车键发送") // 连接成功后的提示// 启动一个goroutine来接收服务器消息go receiveMessages(conn)// 在主goroutine中发送消息sendMessages(conn)
}func receiveMessages(conn net.Conn) {reader := bufio.NewReader(conn)for {// 设置60秒的读取超时conn.SetReadDeadline(time.Now().Add(60 * time.Second))// 读取服务器发送的消息,直到遇到换行符message, err := reader.ReadString('\n')if err != nil {if netErr, ok := err.(net.Error); ok && netErr.Timeout() {fmt.Println("读取超时,未收到服务器消息")continue}fmt.Println("读取错误:", err)return}fmt.Print("服务器: ", message)}
}func sendMessages(conn net.Conn) {scanner := bufio.NewScanner(os.Stdin)for scanner.Scan() {message := scanner.Text()// 设置10秒的写入超时conn.SetWriteDeadline(time.Now().Add(10 * time.Second))// 发送消息到服务器_, err := conn.Write([]byte(message + "\n"))if err != nil {fmt.Println("发送消息错误:", err)return}}
}
2.3 UDP编程
2.3.1 UDP简介
UDP是User Datagram Protocol的缩写,中文名是用户数据报协议。它是OSI参考模型中一种无连 接的传输层协议,提供面向事务的简单不可靠信息传送服务。
UDP协议在网络中与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中位于 第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排 序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需 要在计算机之间传输数据的网络应用,包括网络视频会议系统在内的众多的客户/服务器模式的网 络应用。UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩 盖,但是即使是在今天,UDP仍然不失为一项非常实用和可行的网络传输层协议。
2.3.2 UDP客户端
与TCP客户端类似,创建一个UDP客户端同样使用Dial函数,只需在参数中声明发起的请求协 议为UDP即可
package mainimport ("log""net"
)func main() {// 尝试连接本地1234端口conn, err := net.Dial("udp", ":1234")if err != nil {log.Fatal("连接失败!", err)}defer conn.Close()log.Println("连接成功!")
}
尝试连接本地UDP的1234端口,该端口是关闭的,打印输出的结果如下:
024/07/19 02:22:08 连接成功!
由于UDP是无连接的协议,只关心信息是否成功发送,不关心对方是否成功接收,只要消息 报文发送成功,就不会报错,因此会输出连接成功的信息
2.3.3 UDP服务端
与TCP服务端不同,创建一个UDP服务端无法使用有连接的Listen函数,而要使用无连接的 ListenUDP函数。
基于UDP的协议有很多,如DNS域名解析服务、NTP网络时间协议等。我们来模拟一个最简单的NTP服务器,每当接收到任意字节的信息,就将当前的时间发送给客户端。
服务器 (server.go):
- 在指定端口(8123)上创建UDP监听器。
- 使用无限循环持续监听客户端请求。
- 当收到任何消息时,获取当前时间并发送回客户端。
// 服务器代码 (server.go)
package mainimport ("fmt""net""time"
)func main() {// 在8123端口上监听UDP连接addr, err := net.ResolveUDPAddr("udp", ":8123")if err != nil {fmt.Println("地址解析错误:", err)return}conn, err := net.ListenUDP("udp", addr)if err != nil {fmt.Println("监听错误:", err)return}defer conn.Close()fmt.Println("NTP服务器正在监听 :8123")for {handleClient(conn)}
}func handleClient(conn *net.UDPConn) {buffer := make([]byte, 1024)// 读取客户端发送的数据_, remoteAddr, err := conn.ReadFromUDP(buffer)if err != nil {fmt.Println("读取数据错误:", err)return}fmt.Printf("收到来自 %s 的请求\n", remoteAddr)// 获取当前时间并格式化currentTime := time.Now().Format(time.RFC3339)// 发送时间信息给客户端_, err = conn.WriteToUDP([]byte(currentTime), remoteAddr)if err != nil {fmt.Println("发送响应错误:", err)}
}
客户端 (client.go):
- 连接到指定的服务器地址和端口。
- 发送一个简单的消息("获取时间")到服务器。
- 等待并接收服务器的响应(当前时间)。
- 打印接收到的时间信息。
// 客户端代码 (client.go)
package mainimport ("fmt""net"
)func main() {// 服务器地址serverAddr, err := net.ResolveUDPAddr("udp", "localhost:8123")if err != nil {fmt.Println("地址解析错误:", err)return}// 创建UDP连接conn, err := net.DialUDP("udp", nil, serverAddr)if err != nil {fmt.Println("连接错误:", err)return}defer conn.Close()// 发送任意消息给服务器_, err = conn.Write([]byte("获取时间"))if err != nil {fmt.Println("发送请求错误:", err)return}// 接收服务器响应buffer := make([]byte, 1024)n, _, err := conn.ReadFromUDP(buffer)if err != nil {fmt.Println("接收响应错误:", err)return}// 打印接收到的时间fmt.Printf("服务器时间: %s\n", string(buffer[:n]))
}
使用:
- 先运行服务器:
go run server.go
- 然后在另一个终端运行客户端:
go run client.go
服务器时间: 2024-07-19T02:37:05-07:00
相关文章:
GO:Socket编程
目录 一、TCP/IP协议族和四层模型概述 1.1 互联网协议族(TCP/IP) 1.2 TCP/IP四层模型 1. 网络访问层(Network Access Layer) 2. 网络层(Internet Layer) 3. 传输层(Transport Layer&#…...
wls2下的centos使用桥接模式连接宿主机网络独立静态ip
前提:wsl2已安装,可正常更新 1.在控制面板中,打开开启或关闭windows功能,将里面的 Hyper-V功能打开,此处涉及重启 2. 按一下win键,输入hy,上面可以看到Hyper-V Manager,点进去 3.选择右边的 Vi…...
R语言实现神经网络ANN
# 常用激活函数 # 自定义Sigmoid函数 sigmod <- function(x){return(1/(1exp(-x))) } # 绘制Sigmoid曲线 x <- seq(-10,10,length.out 100) plot(x,sigmod(x),type l,col blue,lwd 2,xlab NA,ylab NA,main Sigmoid函数曲线)# 自定义Tanh函数 tanh <- function(…...
实战:shell脚本练习
高效编写Bash脚本的技巧 总结了10个实用技巧,帮助提高脚本的效率和可靠性,具体包括: 多写注释:在脚本中添加注释,以帮助理解脚本的不同部分。 当运行失败时使脚本退出:使用set -o errexit或set -e&#x…...
常见排序算法总结
文章目录 比较排序冒泡排序选择排序插入排序归并排序快速排序堆排序希尔排序 非比较排序(桶排序)计数排序基数排序 比较排序 冒泡排序 嵌套循环,每次内层循环执行时,数组的每两个元素交换,将一个最大/小的数排到数组…...
网页HTTP协议 get请求和post请求区别?(HTTP中Get、Post、Put与Delete的区别)(HTTP请求方法、HTTP请求方式、HTTP方法)
文章目录 设计GET、POST、DELETE 等多种请求方法的原因1. 符合语义化设计2. 允许服务器对不同的请求方法进行优化处理3. 提高数据传输的安全性4. 遵循现有的网络架构5. 提高网络通信的效率6. 支持 RESTful API 设计 设计GET、POST、DELETE 等多种请求方法的原因 后端之所以要分…...
攻防世界 re新手模式
Reversing-x64Elf-100 64位ida打开 看if语句,根据i的不同,选择不同的数组,后面的2*i/3选择数组中的某一个元素,我们输入的是a1 直接逆向得到就行 二维字符数组写法:前一个是代表有几个字符串,后一个是每…...
Ajax是什么?如何在HTML5中使用Ajax?
Ajax是什么,它如何工作? Ajax是什么 Ajax,全称Asynchronous Javascript And XML(异步JavaScript和XML),是一种创建交互式网页应用的网页开发技术。它允许网页在不重新加载整个页面的情况下,与…...
Python+Flask+MySQL/Sqlite的个人博客系统(前台+后端管理)【附源码,运行简单】
PythonFlaskMySQL/Sqlite的个人博客系统(前台后端管理)【附源码,运行简单】 总览 1、《个人博客系统》1.1 方案设计说明书设计目标工具列表 2、详细设计2.1 管理员登录2.2 程序主页面2.3 笔记新增界面2.4 文章新增界面2.5 文章/笔记管理界面2…...
【Android性能优化】Android CPU占用率检测原理和优化方向
【Android性能优化】Android CPU占用率检测原理和优化方向 CPU相关知识 CPU占用的基本计算公式 (1 - 空闲态运行时间/总运行时间) * 100% Hz、Tick、Jiffies: Hz:Linux核心每隔固定周期会发出timer interrupt (IRQ 0),HZ是用来定义每一秒有…...
AWS Certified Developer Associate备考笔记
AWS Certified Developer Associate备考笔记 缓慢更新中,如果你也正在关注该考试,请点赞后评论感兴趣的章节,可加快我的更新速度 😃 文章目录 AWS Certified Developer Associate备考笔记一、IAM二、EC2三、EC2 Instance Storage…...
数据质量8个衡量标准
在数据驱动的时代,数据质量对于企业的决策和业务运营至关重要。为了确保数据的有效性和可靠性,我们需要根据一些关键要素来衡量数据的质量。本文将介绍数据质量的8个衡量标准,包括准确性、精确性、真实性、及时性、即时性、完整性、全面性和关…...
Redis 跳跃列表与紧凑列表
Redis 跳跃列表(Skip List) 跳跃列表是一种高效的数据结构,它结合了有序数组和链表的优点,能够在 O(log n) 时间内进行插入、删除和查找操作。Redis 使用跳跃列表来实现有序集合(sorted set)的底层数据结构…...
达梦数据库的系统视图v$arch_status
达梦数据库的系统视图v$arch_status 在达梦数据库(DM Database)中,V$ARCH_STATUS 是一个动态性能视图(Dynamic Performance View),用于显示归档日志的状态信息。这个视图可以帮助数据库管理员监控和管理数…...
【Rust光年纪】Rust 中常用的数据库客户端库:核心功能与使用场景
探秘 Rust 语言下的多种数据库客户端库:从安装到实际应用 前言 在现代的软件开发中,数据库是不可或缺的一部分。为了与数据库进行交互,开发人员需要使用各种数据库客户端来执行操作、构建查询等。本文将介绍一些用于 Rust 语言的常见数据库…...
网络安全防御【防火墙双机热备带宽管理综合实验】
目录 一、实验拓扑图 二、实验要求 三、实验思路: 四、实验步骤: 1、FW3的网络相关配置: 2、FW1的新增配置: 3、交换机LSW6(总公司)的新增配置: 4、双机热备技术配置(双机热…...
19.x86游戏实战-创建MFC动态链接库
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 本次游戏没法给 内容参考于:微尘网络安全 工具下载: 链接:https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…...
图论建模技巧搜集
一些经典题目 找可达路径 UVa - 11604 General Sultan 平面图最小割对偶图最短路 UVa - 1376 Animal Run 最小割建模 UVa - 1515 Pool construction 费用流建模 洛谷P3159 [CQOI2012] 交换棋子 一些可以转化为二分图最大权匹配的建模题 UVa1006/LA2238 Fixed Partition Me…...
pytorch学习(九)激活函数
1.pytorch常用激活函数如下: #ReLU激活函数 #Leaky ReLU激活函数 #Sigmoid激活函数 #Tanh激活函数 #Softmax激活函数 #Softplus2.代码 import torch.nn as nn import torch import numpy from torch.utils.tensorboard import SummaryWriterwriter SummaryWriter…...
conda 环境打包与使用
conda 环境导出 使用 Conda 打包环境,可以创建一个可重复使用的环境文件,便于在不同的机器上重新创建相同的环境。以下是具体的步骤: 1. 创建 Conda 环境 如果你还没有创建一个 Conda 环境,可以使用以下命令创建一个新环境&…...
jenkins 插件版本冲突
一、Jenkins安装git parameter 插件重启后报错与临时解决方案 cd /root/.jenkins cp config.xml config.xml.bak vim config.xml <authorizationStrategy class"hudson.security.FullControlOnceLoggedInAuthorizationStrategy"><denyAnonymousReadAcces…...
Python print() 格式化输出
Python print{} 格式化输出 1. print()2. 浮点数 (float)References 1. print() 传递给函数的值称为参数。 引号没有打印在屏幕上,它们只是表示字符串的起止,不是字符串的一部分。可以用这个函数在屏幕上打印出空行,只要调用 print() 就可以…...
【Qt+opencv】计时函数与图像变换
文章目录 前言计算时间函数图像变换旋转镜像缩放 总结 前言 在图像处理和计算机视觉的应用中,我们经常需要对图像进行各种变换,如旋转、缩放、剪切等。同时,为了评估算法的性能,我们也需要对代码的执行时间进行精确的测量。OpenC…...
nodejs下载+react安装
一、nodejs安装 1、nodejs下载 具体安装可参考连接:2023最新版Node.js下载安装及环境配置教程(非常详细)从零基础入门到精通,看完这一篇就够了_nodejs安装及环境配置-CSDN博客 下载地址:Node.js — 下载 Node.js 测…...
linux service小例
linux service 测试 1.创建一个app // myapp.c // 间隔10s写入时间到文件 #include <stdio.h> #include <time.h> #include <unistd.h> // 引入unix标准函数定义,如sleep()int main() {FILE *fp;time_t now;char buffer[80];// 打开文件以追加模…...
iOS 开发包管理之 Swift Package Manager
这是由官方推出,用于管理分发 swift 代码的工具。这个在 Xcode 是天然的存在,就是说我们不用安装就能够直接使用。 File > Add Package Dependencies… 在弹出来窗口选择一些库来导入 又或者点左下角的“” > Add Package Collection… 添加完成…...
【C语言初阶】C语言数组基础:从定义到遍历的全面指南
📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C语言 “ 登神长阶 ” 🤡往期回顾🤡:C语言函数 🌹🌹期待您的关注 🌹🌹 ❀数组 📒1. 什么是数组…...
AI开源战争的真相
引言 在AI技术迅猛发展的今天,开源与闭源之争成为了AI圈内最热的话题之一。大模型免费开放的背后到底隐藏着什么样的真相?这是一个令人困惑的问题。本文将深入探讨开源与闭源之争的历史背景、技术演进以及商业利益的博弈。 开源概念的起源 开源软件的…...
使用Java填充Word模板的技术详解
目录 概述常见的Java Word处理库 Apache POIAspose.Words for JavaDocx4j 使用Apache POI填充Word模板 创建和读取Word文档填充文本填充表格 使用Aspose.Words for Java填充Word模板 创建和读取Word文档填充文本填充表格 使用Docx4j填充Word模板 创建和读取Word文档填充文本填…...
vmware配置centos+配置静态ip联网+更换镜像
centos7配置参考【实战】VMware17虚拟机以及Centos7详细安装教程-CSDN博客 ip配置步骤: 先更改编辑虚拟网络编辑器中的内容 就按照还原默认设置来,设定后就是以上内容,然后一定要记住子网ip和子网掩码 接下来就是NAT设置: 网关…...
金华做网站/长春免费网上推广
新个税法从1月初开始实施。2018年12月31日,国家税务总局推出“个人所得税”APP,方便纳税人线上填报资料进行专项抵扣。几天来这款APP的下载量和注册量大幅增长。随之而来的是,很多商业公司制作的各类“个税”APP也成为热门。这其中有不少纯属…...
云浮网站建设兼职/长沙做搜索引擎的公司
本届TechEd 2009微软技术大会,将于2009年11月5日-7日在北京国家会议中心隆重开幕!不过目前微软还没有给出详细的课程信息,只知道会有6个技术发布:Windows7、Windows Server 2008 R2、Exchange Server 2010、Forefront、System Cen…...
企业网站改版建议/广东seo推广
目标:提高结构化思维,书面表达,公文写作,口头(说话、演讲、讲课)表达能力 谁是我的听众?他们想听什么?他们想怎么听?金字塔原理的基本结构是:结论先行,以上统下ÿ…...
网站建站对象/快速搭建网站的工具
K-means聚类算法(事先数据并没有类别之分!所有的数据都是一样的)1、概述K-means算法是集简单和经典于一身的基于距离的聚类算法采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为类簇是由距离靠近的对象组成…...
山西做网站的公司哪个好/广告开户南京seo
二维平面作图 ? 三维空间作图 ? 符号作图 ? Matlab 绘图过程/原理 2 手工作图如何画出 数学软件 Matlab —— 二维平面作图 —— 三维空间作图 1 本讲主要内容......是通过描点、连线来实现的,故在 画一个曲线图形之前,必须先取得该图形上的 一系列的点的坐标(即横坐标和纵坐…...
wordpress给用户注册/杭州优化排名哪家好
一、相关工具 编译器:VS2019 二、调用步骤 1、首先打开vs2019创建一个控制台应用,如下所示: 2、在类class Program添加对dll文件的引用,例如[DllImport("testdll.dll", EntryPoint "myAdd", ExactSpelling …...