一、用到的net方法
1 、客户端:
var buf [512]byte
tcpAddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:9090")
//向服务器拨号
conn, _ := net.DialTCP("tcp", nil, tcpAddr)
//获取远程服务器地址
rAddr := conn.RemoteAddr()
//发送数据
n, _ := conn.Write([]byte(""))
//接收数据
n, _ = conn.Read(buf[0:])
2、服务器
func ResolveTCPAddr(network, address string) (*TCPAddr, error)
ResolveTCPAddr返回TCP端点的地址。
网络必须是TCP网络名。
如果地址参数中的主机不是字面IP地址或者端口不是字面端口号,那么ResolveTCPAddr将地址解析为TCP端点的地址。
否则,它将地址解析为一对文字IP地址和端口号。
address参数可以使用主机名,但不建议这样做,因为它将最多返回一个主机名的IP地址。
有关网络和地址的描述,请参阅func Dial参数。
network : Tcp Tcp4 Tcp6 address : :9090 应该是访问地址
返回值:*TCPAddr 地址 第二个返回值:err
监听:func ListenTCP(network string, laddr *TCPAddr) (*TCPListener, error)
ListenTCP在本地TCP地址laddr上声明并返回一个*TCPListener,net参数必须是"tcp"、"tcp4"、"tcp6",如果laddr的端口字段为0,函数将选择一个当前可用的端口,可以用Listener的Addr方法获得该端口
第一个参数:TCP 第二个参数 *TCPAddr 地址 返回值 :
具体代码实现
net.go
package main
import (
"fmt"
"log"
"net"
"os"
)
func main() {
tcpAddr, _ := net.ResolveTCPAddr("tcp", ":9090")
//向服务器拨号
conn, _ := net.DialTCP("tcp", nil, tcpAddr)
go HandlerMessage(conn)
//接受来自服务器的消息
buf := make([]byte, 1024)
for {
length, err := conn.Read(buf)
fmt.Println(length)
if err != nil {
log.Printf("recv server msg failed :%v\n", err)
conn.Close()
os.Exit(0)
break
}
fmt.Println(string(buf[0:length]))
}
}
func HandlerMessage(conn net.Conn) {
//获取用户的地址
username := conn.LocalAddr().String()
for {
var input string
//获取用户发送的消息
fmt.Scanln(&input)
if len(input) > 0 {
msg := username + " say " + input
//
_, err := conn.Write([]byte(msg))
if err != nil {
conn.Close()
break
}
}
}
}
server.go
package main
import (
"fmt"
"net"
"os"
)
func main() {
port := "9090"
StartServer(port)
}
func StartServer(p string) {
port := ":" + p
//返回tcp地址
tcpAddr, err := net.ResolveTCPAddr("tcp", port)
fmt.Println(tcpAddr)
if err != nil {
os.Exit(0)
return
}
//监听tcp地址
listener, err := net.ListenTCP("tcp", tcpAddr)
if err != nil {
os.Exit(0)
return
}
buf := make([]byte, 1024)
conns := make(map[string]net.Conn) //用户池
messages := make(chan string, 10) //消息的通道
go BroadCastMessage(conns, messages) //
//每有一个客户进来就将其放入用户池
for {
conn, err := listener.AcceptTCP()
if err != nil {
fmt.Println("Accept failed")
continue
}
conns[conn.RemoteAddr().String()] = conn //将新进来的用户放进用户池
go HandlerMessage(conn, buf, conns, messages) //开一个协程监听用户是否发送消息
}
}
//将收到的信息发送到每一个客户端
func BroadCastMessage(cns map[string]net.Conn, messages chan string) {
for {
messtr := <-messages //接受通道里的消息
//将接收到的消息发送给用户池里的每一个用户
for k, v := range cns {
_, err := v.Write([]byte(messtr)) //发送消息
if err != nil {
delete(cns, k) //如果出现错误 删除用户 结束本次循环
v.Close()
continue
}
}
}
}
//接受用户发送的消息
func HandlerMessage(conn net.Conn, buf []byte, cns map[string]net.Conn, messages chan string) {
for {
length, err := conn.Read(buf)
if err != nil {
conn.Close()
delete(cns, conn.RemoteAddr().String())
break
}
messages <- string(buf[0:length]) //将用户的信息放到通道里
// fmt.Println(string(buf[0:length]))
}
}
OK!