golang p2p udp server
- http://www.dotcoo.com/golang-p2p-udp
- package main
-
- import (
- "net"
- "encoding/binary"
- "encoding/hex"
- "log"
- "time"
- )
-
- const (
- // login client -> server
- CMD_LOGIN byte = byte(iota)
- CMD_LOGIN_RES
-
- // user list server -> client
- CMD_LIST
- CMD_LIST_RES
-
- // ping server -> client
- CMD_PING
- CMD_PONG
-
- // cone client -> client
- CMD_CONE
- CMD_CONE_RES
-
- // message client -> client
- CMD_MEG
- CMD_MSG_RES
- )
-
- var userlist []*net.UDPAddr
- var serverAddr *net.UDPAddr
- var socket *net.UDPConn
-
- func main() {
- var err error
-
- // 设置log参数
- log.SetFlags(log.Lshortfile)
-
- // 用户集合
- userlist = make([]*net.UDPAddr,10)
-
- // 服务器地址
- serverAddr,err = net.ResolveUDPAddr("udp4",":8080")
- log.Println(err)
-
- // 创建监听
- socket,err = net.ListenUDP("udp4",serverAddr)
- if err != nil {
- log.Println("监听失败! ",err)
- return
- }
- defer socket.Close()
-
- // ping
- // go ping()
-
- // 处理
- for {
- // 处理数据报文
- data := make([]byte,4096)
- read,addr,err := socket.ReadFromUDP(data)
- if err != nil {
- log.Println("读取数据失败!",err)
- continue
- }
- log.Printf("UDP: %d,%s,%s\n",read,hex.EncodeToString(data[:read]))
-
- switch data[0] {
- case CMD_LOGIN:
- // 新上线用户的信息
- touser_list_data := make([]byte,15)
- touser_list_data = append(touser_list_data,CMD_LIST_RES,0)
- // touser_list_data = append(touser_list_data,addr.IP...)
- copy(touser_list_data[1:5],addr.IP)
- binary.LittleEndian.PutUint16(touser_list_data[5:],uint16(addr.Port))
-
- log.Println("touser_list_data:",hex.EncodeToString(touser_list_data))
-
- // 构建在线的用户信息列表
- user_list_data := make([]byte,100)
- user_list_data = append(user_list_data,CMD_LIST_RES)
-
- // 通知所有在线用户,有新用户上线
- for _,touser := range userlist {
- // 添加在线用户信息到列表
- // user_list_data = append(user_list_data,touser.IP...)
- user_list_data = append(user_list_data,0)
- copy(user_list_data[len(user_list_data)-6:],touser.IP)
- binary.LittleEndian.PutUint16(user_list_data[len(user_list_data)-2:],uint16(touser.Port))
-
- // 给在线用户发送数据
- socket.WriteToUDP(touser_list_data,touser)
- }
-
- // 给新上限用户发送在线用户的列表
- log.Println("user_list_data:",hex.EncodeToString(user_list_data))
- socket.WriteToUDP(user_list_data,addr)
-
- // 将新用户存储
- userlist = append(userlist,addr)
- case CMD_LOGIN_RES:
- case CMD_LIST:
- case CMD_LIST_RES:
-
- case CMD_PING:
- case CMD_PONG:
- log.Println("CMD_PONG udp: ",addr)
- case CMD_CONE:
- case CMD_CONE_RES:
- case CMD_MEG:
- case CMD_MSG_RES:
- default:
- log.Println("default udp: ",addr)
- }
- }
- }
-
- func ping() {
- ping_data := make([]byte,15)
- ping_data = append(ping_data,CMD_PING,0)
-
- for {
- for _,touser := range userlist {
- socket.WriteToUDP(ping_data,touser)
- }
-
- time.Sleep(5 * time.Second)
- }
- }
golang p2p udp client
- package main
-
- import (
- "fmt"
- "net"
- "log"
- "encoding/binary"
- "encoding/hex"
- "strings"
- "bufio"
- "os"
- )
-
- const (
- // login client -> server
- CMD_LOGIN byte = byte(iota)
- CMD_LOGIN_RES
-
- // user list server -> client
- CMD_LIST
- CMD_LIST_RES
-
- // ping server -> client
- CMD_PING
- CMD_PONG
-
- // cone client -> client
- CMD_CONE
- CMD_CONE_RES
-
- // message client -> client
- CMD_MEG
- CMD_MSG_RES
- )
-
- var userlist []*net.UDPAddr
- var serverAddr *net.UDPAddr
- var listenAddr *net.UDPAddr
- var socket *net.UDPConn
-
- func main() {
- var err error
-
- // 设置log参数
- log.SetFlags(log.Lshortfile)
-
- // 用户集合
- userlist = make([]*net.UDPAddr,"123.123.123.123:8080")
- log.Println("serverAddr",err)
-
- port := 8000
- PORT:
-
- // 本地地址
- listenAddr,fmt.Sprintf(":%d",port))
- if err != nil {
- log.Println(err)
- }
-
- // 创建连接
- socket,listenAddr)
- if err != nil {
- log.Println("连接失败!",err)
- port++
- goto PORT
- return
- }
- defer socket.Close()
-
- // 上线
- login_data := make([]byte,10)
- login_data = append(login_data,CMD_LOGIN)
- login_data = append(login_data,[]byte("nickname")...)
-
- // 发送上线数据
- _,err = socket.WriteToUDP(login_data,serverAddr)
- if err != nil {
- log.Println("发送数据失败!",err)
- return
- }
-
- // 读取消息
- go readMsg()
-
- // 用户交互
- readCmd()
- }
-
- // 用户交互
- func readCmd() {
- for {
- fmt.Printf("p2p > ")
-
- scanner := bufio.NewScanner(os.Stdin)
- if !scanner.Scan() {
- continue
- }
-
- var line = scanner.Text()
- if err := scanner.Err(); err != nil {
- log.Println("read error: ",err)
- continue
- }
-
- switch {
- case strings.HasPrefix(line,"help"):
- fmt.Println(" list: show all user list\n send: send message\n\tsend <id> <message>")
- case strings.HasPrefix(line,"list"):
- fmt.Println("user list:")
- for id,user := range userlist {
- fmt.Println(id+1,user.IP,user.Port)
- }
- case strings.HasPrefix(line,"send"):
- id := 0;
- content := ""
- fmt.Sscanf(line,"send %d %s",&id,&content)
-
- if id <= 0 || id > len(userlist) {
- fmt.Printf("error: id %d not fund\n",id)
- continue
- }
-
- log.Printf("send message: %s %d,%s",userlist[id-1],id,content)
-
- sendData := make([]byte,100)
- sendData = append(sendData,CMD_MEG)
- sendData = append(sendData,[]byte(content)...)
-
- n,err := socket.WriteToUDP(sendData,userlist[id-1])
- log.Println(n,err)
- default:
- fmt.Printf("command error: %s\nuse the 'help' command to get help\n",line)
- }
- }
- }
-
- func readMsg() {
- for {
- // 接收数据
- data := make([]byte,1024)
- read,hex.EncodeToString(data[:read]))
-
- switch data[0] {
- case CMD_LOGIN_RES:
-
- case CMD_LIST_RES:
- for i := 1; i < read; i+=6 {
- addrData := data[i:]
- touser := &net.UDPAddr{
- IP: net.IP(addrData[:4]),Port: int(binary.LittleEndian.Uint16(addrData[4:])),}
-
- coneData := make([]byte,10)
- coneData = append(coneData,CMD_CONE)
- coneData = append(coneData,[]byte("nickname")...)
-
- socket.WriteToUDP(coneData,touser)
- log.Println("cone: ",touser,coneData)
-
- userlist = append(userlist,touser)
- }
- case CMD_PING:
- log.Printf("CMD_PING\n")
- pong_data := make([]byte,15)
- pong_data = append(pong_data,CMD_PONG,1)
- n,err := socket.WriteTo(pong_data,addr)
- log.Println("CMD_PING: ",n,err)
- case CMD_PONG:
-
- case CMD_CONE:
- coneResData := make([]byte,10)
- coneResData = append(coneResData,CMD_CONE_RES)
- coneResData = append(coneResData,[]byte("nickname")...)
-
- socket.WriteToUDP(coneResData,addr)
- case CMD_CONE_RES:
- log.Println("CMD_CONE_RES:",addr)
- case CMD_MEG:
- fmt.Println(string(data[1:read]))
- case CMD_MSG_RES:
-
- default:
- log.Println("default UDP: ",data[0])
- }
- }
- }