原生Golang 实现聊天室

服务器端代码:

package main

import (
	"fmt"
	"os"
	"net"
	"strings"
	"log"
)

const LOG_DIRECTORY  =  "E:\\project\\mygo\\src\\chatRoom\\log.log"
var  onlineConns = make(map[string]net.Conn)
var messageQueue = make(chan string, 1000)
var quitChan  = make(chan bool)
var logger *log.Logger


func CheckError(err error)  {
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(1)
	}
}

func ProcessInfo(conn net.Conn)  {
	buf := make([]byte, 1024)
	defer func(conn net.Conn) {
		addr := fmt.Sprintf("%s", conn.RemoteAddr())
		delete(onlineConns, addr)
		conn.Close()
		for i := range onlineConns {
			fmt.Println(i)
		}
	}(conn)

	for  {
		numOfBytes, err := conn.Read(buf)
		if err != nil {
			continue
		}
		if numOfBytes != 0 {
			message := string(buf[0:numOfBytes])
			messageQueue <- message
			//remoteAddr := conn.RemoteAddr()
			//fmt.Println(remoteAddr)
			//fmt.Printf("Has received this message:%s\n", string(buf[0:numOfBytes]))
		}
	}
}

func ConsumeMessage()  {
	for  {
		select {
		case message := <- messageQueue:
			//对消息进行解析
			doProcessMessage(message)
		case <- quitChan:
			break

		}
	}
}

func doProcessMessage(message string)  {
	contents := strings.Split(message, "#")
	if len(contents) > 1 {
		addr := contents[0]
		sendMessage := strings.Join(contents[1:], " ")
		addr = strings.Trim(addr, " ")
		if conn, ok := onlineConns[addr]; ok {
			_, err := conn.Write([]byte(sendMessage))
			if err != nil {
				fmt.Println("消息发送失败!")
			}
		}
	}else {
		contents := strings.Split(message, "*")
		if strings.ToUpper(contents[1]) == "LIST" {
			var ips string = ""
			for i := range onlineConns{
				ips = ips + "|" + i
			}
			if conn, ok := onlineConns[contents[0]]; ok {
				_, err := conn.Write([]byte(ips))
				if err != nil {
					fmt.Println("消息发送失败!")
				}
			}
		}

	}
}

func main()  {
	logFile, err := os.OpenFile(LOG_DIRECTORY, os.O_RDWR|os.O_CREATE, 0)
	if err != nil {
		fmt.Println("log File 创建失败!")
		os.Exit(-1)
	}
	defer logFile.Close()
	logger = log.New(logFile, "\r\n", log.Ldate|log.Ltime|log.Llongfile)
	listen_socket, err := net.Listen("tcp", "127.0.0.1:8900")
	CheckError(err)
	defer listen_socket.Close()
	fmt.Println("聊天室已经开始运行!\n")
	logger.Println("写入日志!")

	go ConsumeMessage()

	for {
		conn, err := listen_socket.Accept()
		CheckError(err)
		addr := fmt.Sprintf("%s", conn.RemoteAddr())
		onlineConns[addr] =conn
		for i := range onlineConns {
			fmt.Println(i)
		}
		go ProcessInfo(conn)
	}
	
}

客户端代码:

package main

import (
	"os"
	"net"
	"fmt"
	"bufio"
	"strings"
)

func CheckError(err error) {
	if err != nil {
		fmt.Printf("s%", err)
		os.Exit(1)
	}

}

func MessageSend(conn net.Conn)  {
	var input string
	for   {
		reader := bufio.NewReader(os.Stdin)
		data, _ , _ := reader.ReadLine()
		input = string(data)
		//fmt.Println(strings.ToUpper(input))
		if strings.ToUpper(input) == "EXIT" {
			fmt.Println("关闭连接")
			conn.Close()
			break
		}

		_, err := conn.Write([]byte(input))
		if err != nil {
			conn.Close()
			fmt.Println("客户端连接错误:"+err.Error())
			break
		}
	}
}


func main()  {
	conn, err := net.Dial("tcp", "127.0.0.1:8900")
	CheckError(err)
	defer conn.Close()
	//conn.Write([]byte("Hello Golang!"))
	go MessageSend(conn)
	buf := make([]byte, 1024)
	for  {
		length, err := conn.Read(buf)
		if err != nil {
			fmt.Println("您已退出!")
			os.Exit(0)
		}
		if length != 0 {
			CheckError(err)
			fmt.Println("收到消息,消息内容:"+ string(buf))
		}

	}

	fmt.Print("消息已经发送!")

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
golang websocekt 聊天室流程一般包括以下几个步骤: 1. 建立服务端:首先需要编写一个基于golang的websocekt服务端,负责接收客户端连接,并处理客户端发送的消息。可以使用gorilla/websocket库来实现websocekt服务端的搭建,通过gorilla/websocket库提供的函数来处理连接、消息的读取和发送等操作。 2. 处理消息:服务端需要实现消息的处理逻辑,包括接收客户端发送的消息、广播消息给所有在线的客户端等功能。可以使用goroutine来实现并发处理消息,从而提高聊天室的并发能力。 3. 建立客户端:客户端可以是基于web浏览器的前端页面,也可以是基于golang的命令行程序。通过gorilla/websocket库提供的javascript接口或者golang客户端库来与服务端建立websocekt连接,并发送消息、接收消息。 4. 消息交互:一旦客户端与服务端建立websocekt连接,客户端就可以发送消息到服务端,服务端接收到消息后可以进行广播给所有在线的客户端,或者私发给指定的客户端。 5. 安全考虑:在实现websocekt聊天室的过程中,需要注意安全方面的考虑,比如防止恶意攻击、防止恶意消息、限制连接数等方面的问题。 通过以上几个步骤,就可以实现一个基于golang websocekt的聊天室。在实际项目中,还可以加入更多功能,比如用户身份认证、消息记录、图片、文件的发送等功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值