一、用到的net方法
1 、客戶端:
var buf [512]byte
tcpAddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:9090")
//向服務(wù)器撥號
conn, _ := net.DialTCP("tcp", nil, tcpAddr)
//獲取遠程服務(wù)器地址
rAddr := conn.RemoteAddr()
//發(fā)送數(shù)據(jù)
n, _ := conn.Write([]byte(""))
//接收數(shù)據(jù)
n, _ = conn.Read(buf[0:])
2、服務(wù)器
func ResolveTCPAddr(network, address string) (*TCPAddr, error)
ResolveTCPAddr返回TCP端點的地址。
網(wǎng)絡(luò)必須是TCP網(wǎng)絡(luò)名。
如果地址參數(shù)中的主機不是字面IP地址或者端口不是字面端口號,那么ResolveTCPAddr將地址解析為TCP端點的地址。
否則,它將地址解析為一對文字IP地址和端口號。
address參數(shù)可以使用主機名,但不建議這樣做,因為它將最多返回一個主機名的IP地址。
有關(guān)網(wǎng)絡(luò)和地址的描述,請參閱func Dial參數(shù)。
network : Tcp Tcp4 Tcp6 address : :9090 應(yīng)該是訪問地址
返回值:*TCPAddr 地址 第二個返回值:err
監(jiān)聽:func ListenTCP(network string, laddr *TCPAddr) (*TCPListener, error)
ListenTCP在本地TCP地址laddr上聲明并返回一個*TCPListener,net參數(shù)必須是"tcp"、"tcp4"、"tcp6",如果laddr的端口字段為0,函數(shù)將選擇一個當前可用的端口,可以用Listener的Addr方法獲得該端口
第一個參數(shù):TCP 第二個參數(shù) *TCPAddr 地址 返回值 :
具體代碼實現(xiàn)
net.go
package main
import (
"fmt"
"log"
"net"
"os"
)
func main() {
tcpAddr, _ := net.ResolveTCPAddr("tcp", ":9090")
//向服務(wù)器撥號
conn, _ := net.DialTCP("tcp", nil, tcpAddr)
go HandlerMessage(conn)
//接受來自服務(wù)器的消息
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
//獲取用戶發(fā)送的消息
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
}
//監(jiān)聽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) //開一個協(xié)程監(jiān)聽用戶是否發(fā)送消息
}
}
//將收到的信息發(fā)送到每一個客戶端
func BroadCastMessage(cns map[string]net.Conn, messages chan string) {
for {
messtr := <-messages //接受通道里的消息
//將接收到的消息發(fā)送給用戶池里的每一個用戶
for k, v := range cns {
_, err := v.Write([]byte(messtr)) //發(fā)送消息
if err != nil {
delete(cns, k) //如果出現(xiàn)錯誤 刪除用戶 結(jié)束本次循環(huán)
v.Close()
continue
}
}
}
}
//接受用戶發(fā)送的消息
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!