Go语言 之聊天室 服务器实现中转

clinet

// chatroom_client
package main

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

func CheckError(err error) {
	if err != nil {
		panic(err)
	}
}

func MessageSend(conn net.Conn) {
	var input string
	for {
		//接收系统标准输入
		reader := bufio.NewReader(os.Stdin)
		data, _, _ := reader.ReadLine()
		input = string(data)

		//如果客户端输入exit 表示要结束连接
		if strings.ToUpper(input) == "EXIT" {
			conn.Close()
			break
		}

		_, err := conn.Write([]byte(input))
		if err != nil {
			conn.Close()
			fmt.Println("client connect failure: " + err.Error())
			break
		}
	}
}

func main() {
	conn, err := net.Dial("tcp", "127.0.0.1:8080")
	CheckError(err)
	defer conn.Close()

	//开启消息发送协程
	go MessageSend(conn)


	//主协程负责接收消息
	buf := make([]byte, 1024)
	for {
		numOfBytes, err := conn.Read(buf)
		CheckError(err)

		/*结尾buf[0:numOfBytes]的原因是:numOfBytes是指接收的字节数 如果只用string(buf)
	    	可能会导致接收字符串中有其他之前接收的字符
	    */
		fmt.Println("receive server message content:" + string(buf[0:numOfBytes]))
	}

	fmt.Println("Client program end!")
}

  sever:

// chatroom server
package main

import (
	"fmt"
	"net"
	"strings"
)

var onlineConns = make(map[string]net.Conn)//存储客户端链接映射 key为链接ip:port value为连接对象conn
var messageQueue = make(chan string, 1000)//消息队列 带缓冲的buf

var quitChan = make(chan bool)

func CheckError(err error) {
	if err != nil {
		panic(err)
	}
}

//消息接收协程
func ProcessInfo(conn net.Conn) {
	buf := make([]byte, 1024)
	defer conn.Close()

	for {
		numOfBytes, err := conn.Read(buf)
		if err != nil {
			break
		}

		if numOfBytes != 0 {
			/*结尾buf[0:numOfBytes]的原因是:numOfBytes是指接收的字节数 如果只用string(buf)
	    		可能会导致接收字符串中有其他之前接收的字符
	    	*/
			message := string(buf[0:numOfBytes])

			//将消息放入到消息队列
			messageQueue <- message
		}
	}
}

//消费者协程
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 := contents[1]

		addr = strings.Trim(addr, " ")

		//通过addr查看是否有链接对象
		if conn, ok := onlineConns[addr]; ok {
			_, err := conn.Write([]byte(sendMessage))
			if err != nil {
				fmt.Println("online conns send failure!")
			}
		}
	}
}

func main() {
	listen_socket, err := net.Listen("tcp", "127.0.0.1:8080")
	CheckError(err)
	defer listen_socket.Close()

	fmt.Println("Server is waiting....")

	go ConsumeMessage()

	for {
		conn, err := listen_socket.Accept()
		CheckError(err)

		//将conn存储到onlineConns映射表中
		addr := fmt.Sprintf("%s", conn.RemoteAddr())
		onlineConns[addr] = conn
		for i := range onlineConns {
			fmt.Println(i)
		}

		go ProcessInfo(conn)
	}
}

  

posted @ 2017-10-26 20:33  czcColud  阅读(226)  评论(0编辑  收藏  举报