用go写socket非常简单,如果你了解其他语言的socket的话一看便知,如果想深入的话,个人建议看uninx网络编程套接字联网API这本书。
在go中,网络协议被封装的非常完好了,我们并不需要像其他语言那样需要socket、bind、listen、receive、connect等一系列的操作,只需要go中自带的net包就可以很方便的完成socket编程。
server.go
package main
import (
"fmt"
"net"
"log"
"os"
)
func main() {
//建立socket,监听端口
netListen, err := net.Listen("tcp", "localhost:1024")
CheckError(err)
defer netListen.Close()
Log("Waiting for clients")
for {
conn, err := netListen.Accept()
if err != nil {
continue
}
Log(conn.RemoteAddr().String(), " tcp connect success")
handleConnection(conn)
}
}
//处理连接
func handleConnection(conn net.Conn) {
buffer := make([]byte, 2048)
for {
n, err := conn.Read(buffer)
if err != nil {
Log(conn.RemoteAddr().String(), " connection error: ", err)
return
}
Log(conn.RemoteAddr().String(), "receive data string:\n", string(buffer[:n]))
}
}
func CheckError(err error) {
if err != nil {
fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
os.Exit(1)
}
}
client.go
这里客户端使用stdin读取输入,具体情况请大家自己运行实例中的代码即可
package main
import (
"fmt"
"net"
"os"
"bufio"
)
func sender(conn net.Conn) {
r := bufio.NewReader(os.Stdin) /*使用bufio缓冲器*/
for{
rawLine, _, _ := r.ReadLine()
line := string(rawLine)
conn.Write([]byte(line))
fmt.Println("send over")
}
}
func main() {
tcpAddr, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:1024")
if err != nil {
fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
os.Exit(1)
}
conn, err := net.DialTCP("tcp", nil, tcpAddr)
if err != nil {
fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
os.Exit(1)
}
fmt.Println("connect success")
sender(conn)
}
大家看看,是不是很简单呢。server端主要用到Listen、Accept、Read三个主要的函数
netListen, err := net.Listen("tcp", "localhost:1024")
conn, err := netListen.Accept()
n, err := conn.Read(buffer)
client端就用到DialTCP这个主要的api,请大家自行查阅这个函数的用法.
Go语言中通过net包中的DialTCP函数建议一个TCP连接,返回一个TCPConn类型,客户端和服务器段通过这个类型来进行数据交换。一般而言,客户端通过TCPConn写入请求信息发送到服务器端,读取服务器端反馈的信息。这个链接只有当任意一遍关闭了连接之后才失效,不然我们都可以一直使用。函数定义
func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err os.Error)
net包中有一个类型TCPConn,这个类型可以用来作为客户端和服务器端交互的通道,他有两个主要的函数:
func (c *TCPConn) Write(b []byte) (n int, err os.Error)
func (c *TCPConn) Read(b []byte) (n int, err os.Error)
通过以上这个例子我们就可以搭建一个socket的server-clinet框架。
如果在handleConnection(conn net.Conn)这句前面加一个go就可以让服务端并发的出来不同的client了,其中go是go语言中的关键字,go语言中支持轻量级线程(协程)goroutine