Go语言简单的TCP编程
前期准备
- 需要
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.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退出聊天 - 只使用一套代码,通过命令行参数启动服务器还是客户端
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])
} }
Go语言简单的TCP编程的更多相关文章
- go实现简单的tcp编程
服务端的代码 package main import ( "fmt" "net" ) func main () { fmt.Println("star ...
- 网络编程----------SOCKET编程实现简单的TCP协议
首先我们须要大致了解TCP的几点知识: 1.TCP的特点:面向连接的可靠性传输 2.TCP的三次握手建立连接和四次挥手释放连接.但为什么TCP要三次握手建立连接呢? 答:由于两次握手无法保证可靠性.若 ...
- TCP编程,Socket通讯
网络编程分两种,一种是TCP编程,还有一种是UDP编程(点击打开链接).而本文先讲述简单的TCP编程,Socket套接字连接通讯,实现简单的client与server之间的信息传输. 以下是clien ...
- C#socket编程之实现一个简单的TCP通信
TCP(TransmissionControl Protocol)传输控制协议. 是一种可靠的.面向连接的协议(eg:打电话).传输效率低全双工通信(发送缓存&接收缓存).面向字节流.使用TC ...
- Python之路(第三十一篇) 网络编程:简单的tcp套接字通信、粘包现象
一.简单的tcp套接字通信 套接字通信的一般流程 服务端 server = socket() #创建服务器套接字 server.bind() #把地址绑定到套接字,网络地址加端口 server.lis ...
- Mina、Netty、Twisted一起学(一):实现简单的TCP服务器
MINA.Netty.Twisted为什么放在一起学习?首先,不妨先分别看一下它们官方网站对其的介绍: MINA: Apache MINA is a network application frame ...
- python中的TCP编程学习
今天看了一下关于python的TCP编程. 发现思路和其他语言(比如java)思路基本上差点儿相同. 先看client.基本过程例如以下: 第一步:创建一个socket 第二步:建立连接 第三步:发送 ...
- go语言之行--网络编程、http处理流程详情
一.简介 go语言中的网络编程主要通过net包实现,net包提供了网络I/O接口,包括HTTP.TCP/IP.UDP.域名解析和Unix域socket等.和大多数语言一样go可以使用几行代码便可以启动 ...
- 牛客网Java刷题知识点之TCP、UDP、TCP和UDP的区别、socket、TCP编程的客户端一般步骤、TCP编程的服务器端一般步骤、UDP编程的客户端一般步骤、UDP编程的服务器端一般步骤
福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号: 大数据躺过的坑 Java从入门到架构师 人工智能躺过的坑 Java全栈大联盟 ...
随机推荐
- Python:staticmethod vs classmethod
Being educated under Java background, static method and class method are the same thing. But not so ...
- JQuery DataTables Editor---只修改页面内容
近来在工作中需要对JQuery DataTables进行增,删,改的操作,在网上找了一些资料,感觉比较的好的就是(http://editor.datatables.net/)文章中所展示的操作方法(如 ...
- 不调用库函数实现 strCpy
实现函数时,首先要弄清楚特殊情况,边界条件要搞清. char* strCpy(char* src,char* des){ //判断指针是否为空 if(NULL==src||NULL == des) r ...
- 没有产品,没有用户的,绝对不要浪费时间去联系风投——没有过home run的创业人,想办法先做出产品,找到少量用户,没有任何销售成本
著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:Kuan Huang链接:http://www.zhihu.com/question/19641135/answer/1353 ...
- snort简介以及在Ubuntu下的安装
一.简介 Snort是一套开放源代码的网络入侵预防软件与网络入侵检测软件.Snort使用了以侦测签章(signature-based)与通信协议的侦测方法.Snort是一个免费的IDS(入侵监测系统) ...
- MyGui笔记(1)建立第一个工程
记录下学习 MyGui的一些笔记,从建立第一个工程开始. 步骤: 1.右键MYGUI解决方案,添加→新建项目,选择“Win32 项目”,名称为:TestHello.下一步,勾选“空项目”. 2.设置工 ...
- MySQL存储过程的基本函数
(1).字符串类 CHARSET(str) //返回字串字符集 CONCAT (string2 [,... ]) //连接字串 INSTR (string ,substring ) //返回subst ...
- 一封在JSP课程结束之后给学生的信
<JSP应用程序设计>这门课终于考完了,虽然题目有点难,但我看大部分同学考的还可以,算上平时成绩应该都能拿到一个满意的分数. 再次感谢大家一个学期来对我的支持,跟大家一起的这个学期很开心, ...
- 用C#实现生成PDF文档
using System; using System.IO; using System.Text; using System.Collections; namespace PDFGenerator { ...
- Hadoop学习之编译eclipse插件
近期准备開始学习Hadoop1.2.1的源码,感觉最好的方法还是能够在运行Hadoop及hadoop作业时跟踪调试代码的实际运行情况.因为选择的IDE为eclipse,所以准备编译一下hadoop的e ...