简单的TCP多客户端聊天
服务器每收到一个连接,就让一个goroutine去通过sock和客户端进行交流。goroutine执行流程,先接受信息,在发送信息。
客户端从终端获取输入,发送给指定IP和端口的服务器,接受服务器的信息。
虽然可以实现多客户端通信,但是两个客户端有两个终端,服务器只有一个终端。由标准输入获取的信息发送给服务器端上一次接受信息的客户端(服务端上一次接受完客户端信息之后的goroutine阻塞在从标准输入获取信息那里了)
服务器
package main
import (
"bufio"
"fmt"
"net"
"os"
)
func log(msg string, err error) {
fmt.Println(msg, err)
os.Exit(-1)
}
func work(sock net.Conn) {
for {
var buf [1024]byte
n, err := sock.Read(buf[:])
if err != nil {
log("读数据出错:", err)
}
fmt.Printf("%v说:%v", sock.RemoteAddr().String(), string(buf[:n]))
var str string
reader := bufio.NewReader(os.Stdin)
str, err = reader.ReadString('\n')
if err != nil {
fmt.Println("发送失败:", err)
os.Exit(-1)
}
sock.Write([]byte(str))
}
}
func main() {
listenSock, err := net.Listen("tcp", "127.0.0.1:8000")
if err != nil {
log("监听失败:", err)
}
for {
connectSock, err := listenSock.Accept()
defer connectSock.Close()
if err != nil {
log("接受请求失败:", err)
}
go work(connectSock)
}
}
客户端
package main
import (
"bufio"
"fmt"
"net"
"os"
)
func main() {
server, err := net.Dial("tcp", "127.0.0.1:8000")
if err != nil {
fmt.Println("拨号失败:", err)
os.Exit(-1)
}
defer server.Close()
for {
var str string
var buf [1024]byte //字节数组
reader := bufio.NewReader(os.Stdin)
str, err = reader.ReadString('\n')
if err != nil {
fmt.Println("发送失败:", err)
os.Exit(-1)
}
server.Write([]byte(str))
var n int
n, err = server.Read(buf[:])
if err != nil {
fmt.Println("读取失败:", err)
os.Exit(-1)
}
fmt.Printf("%v说:%v", server.RemoteAddr().String(), string(buf[:n]))
}
}
简单的UDP多客户端聊天
UDP服务器无连接,接受到消息,讲消息输出,在回复“收到”字样。
服务器处于死循环中,任何客户端只要客户端拨号的IP和端口是UDP服务器的IP和端口,该udp服务器都可以接受,也不需要额外goroutine来处理多个客户端的消息。
服务器
package main
import (
"fmt"
"net"
"os"
)
func main() {
conn, err := net.ListenUDP("udp", &net.UDPAddr{
IP: net.ParseIP("127.0.0.1"),
Port: 9999,
})
if err != nil {
fmt.Println("ListenUDP erro:", err)
os.Exit(-1)
}
defer conn.Close()
for {
var buf [1024]byte
n, addr, err := conn.ReadFromUDP(buf[:])
if err != nil {
fmt.Println("接受消息出错:", err)
}
fmt.Println(addr.String(), string(buf[:n]))
conn.WriteToUDP([]byte("收到"), addr)
}
}
客户端
package main
import (
"bufio"
"fmt"
"net"
"os"
"strings"
)
func main() {
con, err := net.DialUDP("udp", nil, &net.UDPAddr{
IP: net.ParseIP("127.0.0.1"),
Port: 9999,
})
if err != nil {
fmt.Println("拨号失败:", err)
}
for {
reader := bufio.NewReader(os.Stdin)
str, _ := reader.ReadString('\n')
str = strings.Trim(str, "\r\n") //去掉换行符,好和Q比较
if strings.ToUpper(str) == "Q" {
fmt.Println("退出聊天系统")
return //退出
}
con.Write([]byte(str))
var buf [1024]byte
n, _, _ := con.ReadFromUDP(buf[:])
fmt.Println(con.RemoteAddr().String(), string(buf[:n]))
}
}