Go语言简单的TCP编程
时间:2022-05-05
本文章向大家介绍Go语言简单的TCP编程,主要内容包括前期准备、TCP Client、TCP Server、一个例子、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
前期准备
- 需要
import "net"
包 -
IP
类型,其中一个重要的方法是IP.ParseIP(ipaddr string)
来判断是否是合法的IP地址
TCP Client
-
func (c *TCPConn) Write(b []byte) (n int, err os.Error)
用于发送数据,返回发送的数据长度或者返回错误,是TCPConn
的方法 -
func (c *TCPConn) Read(b []byte) (n int, err os.Error)
用于接收数据,返回接收的长度或者返回错误,是TCPConn
的方法 -
TCPAddr
类型,保存TCP的地址信息,包括地址和端口 type TCPAddr struct { IP IP Port int } -
func ResolveTCPAddr(net, addr string) (*TCPAddr, os.Error)
获取一个TCPAddr
,参数都是string
类型,net是个const string
,包括tcp4
,tcp6
,tcp
一般使用tcp
,兼容v4和v6,addr
表示ip地址,包括端口号,如www.google.com:80
之类的 -
func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err os.Error)
用来连接(connect)到远程服务器上,net表示协议方式,tcp
,tcp4
或者tcp6
,laddr
表示本机地址,一般为nil
,raddr
表示远程地址,这里的laddr
和raddr
都是TCPAddr
类型的,一般是上一个函数的返回值。 - 作为一个TCP的客户端,基本的操作流程如下: service="www.google.com:80" tcpAddr, err := net.ResolveTCPAddr("tcp4", service) conn, err := net.DialTCP("tcp", nil, tcpAddr) _, err = conn.Write([]byte("HEAD / HTTP/1.0rnrn")) _, err = conn.Read(b) / result, err := ioutil.ReadAll(conn)
TCP Server
-
func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err os.Error)
用来监听端口,net
表示协议类型,laddr
表示本机地址,是TCPAddr
类型,注意,此处的laddr包括端口,返回一个*TCPListener
类型或者错误 -
func (l *TCPListener) Accept() (c Conn, err os.Error)
用来返回一个新的连接,进行后续操作,这是TCPListener
的方法,一般TCPListener
从上一个函数返回得来。 - 服务器的基本操作流程为: service:=":9090" tcpAddr, err := net.ResolveTCPAddr("tcp4", service) l,err := net.ListenTCP("tcp",tcpAddr) conn,err := l.Accept() go Handler(conn) //此处使用go关键字新建线程处理连接,实现并发
一个例子
需求
实现一个公共聊天服务器。
- 服务器接收客户端的信息
- 接收完以后将客户端的信息发送到所有的客户端上
- 客户端使用
/quit
退出聊天 - 只使用一套代码,通过命令行参数启动服务器还是客户端
实现:
package main
import(
"fmt"
"os"
"net"
)
////////////////////////////////////////////////////////
//
//错误检查
//
////////////////////////////////////////////////////////
func checkError(err error,info string) (res bool) {
if(err != nil){
fmt.Println(info+" " + err.Error())
return false
}
return true
}
////////////////////////////////////////////////////////
//
//服务器端接收数据线程
//参数:
// 数据连接 conn
// 通讯通道 messages
//
////////////////////////////////////////////////////////
func Handler(conn net.Conn,messages chan string){
fmt.Println("connection is connected from ...",conn.RemoteAddr().String())
buf := make([]byte,1024)
for{
lenght, err := conn.Read(buf)
if(checkError(err,"Connection")==false){
conn.Close()
break
}
if lenght > 0{
buf[lenght]=0
}
//fmt.Println("Rec[",conn.RemoteAddr().String(),"] Say :" ,string(buf[0:lenght]))
reciveStr :=string(buf[0:lenght])
messages <- reciveStr
}
}
////////////////////////////////////////////////////////
//
//服务器发送数据的线程
//
//参数
// 连接字典 conns
// 数据通道 messages
//
////////////////////////////////////////////////////////
func echoHandler(conns *map[string]net.Conn,messages chan string){
for{
msg:= <- messages
fmt.Println(msg)
for key,value := range *conns {
fmt.Println("connection is connected from ...",key)
_,err :=value.Write([]byte(msg))
if(err != nil){
fmt.Println(err.Error())
delete(*conns,key)
}
}
}
}
////////////////////////////////////////////////////////
//
//启动服务器
//参数
// 端口 port
//
////////////////////////////////////////////////////////
func StartServer(port string){
service:=":"+port //strconv.Itoa(port);
tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
checkError(err,"ResolveTCPAddr")
l,err := net.ListenTCP("tcp",tcpAddr)
checkError(err,"ListenTCP")
conns:=make(map[string]net.Conn)
messages := make(chan string,10)
//启动服务器广播线程
go echoHandler(&conns,messages)
for {
fmt.Println("Listening ...")
conn,err := l.Accept()
checkError(err,"Accept")
fmt.Println("Accepting ...")
conns[conn.RemoteAddr().String()]=conn
//启动一个新线程
go Handler(conn,messages)
}
}
////////////////////////////////////////////////////////
//
//客户端发送线程
//参数
// 发送连接 conn
//
////////////////////////////////////////////////////////
func chatSend(conn net.Conn){
var input string
username := conn.LocalAddr().String()
for {
fmt.Scanln(&input)
if input == "/quit"{
fmt.Println("ByeBye..")
conn.Close()
os.Exit(0);
}
lens,err :=conn.Write([]byte(username + " Say :::" + input))
fmt.Println(lens)
if(err != nil){
fmt.Println(err.Error())
conn.Close()
break
}
}
}
////////////////////////////////////////////////////////
//
//客户端启动函数
//参数
// 远程ip地址和端口 tcpaddr
//
////////////////////////////////////////////////////////
func StartClient(tcpaddr string){
tcpAddr, err := net.ResolveTCPAddr("tcp4", tcpaddr)
checkError(err,"ResolveTCPAddr")
conn, err := net.DialTCP("tcp", nil, tcpAddr)
checkError(err,"DialTCP")
//启动客户端发送线程
go chatSend(conn)
//开始客户端轮训
buf := make([]byte,1024)
for{
lenght, err := conn.Read(buf)
if(checkError(err,"Connection")==false){
conn.Close()
fmt.Println("Server is dead ...ByeBye")
os.Exit(0)
}
fmt.Println(string(buf[0:lenght]))
}
}
////////////////////////////////////////////////////////
//
//主程序
//
//参数说明:
// 启动服务器端: Chat server [port] eg: Chat server 9090
// 启动客户端: Chat client [Server Ip Addr]:[Server Port] eg: Chat client 192.168.0.74:9090
//
////////////////////////////////////////////////////////
func main(){
if len(os.Args)!=3 {
fmt.Println("Wrong pare")
os.Exit(0)
}
if os.Args[1]=="server" && len(os.Args)==3 {
StartServer(os.Args[2])
}
if os.Args[1]=="client" && len(os.Args)==3 {
StartClient(os.Args[2])
}
}
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 纯小白都能看懂的《单个神经元》、《随机梯度下降》、《逻辑与》
- 使用Flutter开发的抖音国际版实例代码详解
- vue-cropper裁剪图片
- Android 开发使用PopupWindow实现弹出警告框的复用类示例
- python初学者笔记—关于 random 和 time 模块
- Android自定义日历效果
- Android 开发使用PopupWindow实现加载等待界面功能示例
- Android自定义控件实现圆形进度CircleProgressBar
- Android Studio如何查看源码并调试的方法步骤
- Flutter中mixin的使用详解
- android实现圆形渐变进度条
- 如何在Android Studio下进行NDK开发
- flutter中build.gradle仓库的配置(解决外网下载速度过慢失败的问题)
- Android studio 实现随机位置画10个随机大小的五角星的代码
- 详解Android Studio实现用户登陆界面demo(xml实现)