前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go语言简单的TCP编程

Go语言简单的TCP编程

作者头像
李海彬
发布2018-03-26 13:03:15
1K0
发布2018-03-26 13:03:15
举报
文章被收录于专栏:Golang语言社区Golang语言社区

前期准备


  • 需要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或者tcp6laddr表示本机地址,一般为nilraddr表示远程地址,这里的laddrraddr都是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.0\r\n\r\n")) _, 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退出聊天
  • 只使用一套代码,通过命令行参数启动服务器还是客户端

实现:

代码语言:javascript
复制
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])  
    }  
 
 
}  

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-02-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Golang语言社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前期准备
  • TCP Client
  • TCP Server
  • 一个例子
    • 需求
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档