go语言聊天室

这个是自己做了一点修改,如果是原版的方法,客户端在字符串中添加空格的时候,那个方法scanln会自动分割空格两端的字符串,从而错乱,所以改了这个版本(就是客户端在想服务端的通道出入数据的时候的一点修改),初学炸到,不喜勿喷 

package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
)
/**
主程序  启动客户端和服务端
参数说明:
  启动服务器端:  go run main.go server [port]             eg: go run main.go server 9090
  启动客户端:   go run main.go [Server Ip Addr]:[Server Port]    eg: go run main.go client :9090
 */
func main()  {
	if len(os.Args) != 3 {
		fmt.Println("wrong params")
		os.Exit(0)
	}
	if os.Args[1] == "server" {
		StartServer(os.Args[2])
	}
	if os.Args[1] == "client" {
		StartClient(os.Args[2])
	}
}

/**
启动服务器
参数:port 端口号
 */
func StartServer(port string)  {
	service := ":" + port
	tcpAddr,err := net.ResolveTCPAddr("tcp4", service)
	checkError(err, "ResolveTCPAddr")
	l,err := net.ListenTCP("tcp", tcpAddr)
	checkError(err ,"ListenTCP")
	conns := make(map[string]net.Conn)
	messages := make(chan string, 10)

	//启动服务器广播线程 :向所有客户端发送消息
	go echoHandler(&conns, messages)

	for {
		fmt.Println("Listening ...")
		conn,err := l.Accept()//返回一个新的连接
		checkError(err , "l.Accept")
		fmt.Println("Accepting ...")
		conns[conn.RemoteAddr().String()] = conn
		//启动一个接受客户端发送消息的线程
		go Handler(conn, messages)
	}
}
/**
服务器发送数据的线程:向所有客户端发送消息
参数
   连接字典 conns
   数据通道 messages
 */
func echoHandler(conns *map[string]net.Conn, messages chan string)  {
	for {
		//向通道中传入数据
		msg := <-messages
		fmt.Println(msg)

		for key,con := range *conns {
			fmt.Println("connection is connected from ...", key)
			_,err := con.Write([]byte(msg))
			if err != nil {
				fmt.Println(err)
				delete(*conns, key)
			}
		}

	}
}

/**
服务器端接收客户端数据线程
参数:
    据连接 conn
    通讯通道 messages
 */
func Handler(conn net.Conn, messages chan string)  {
	fmt.Println("connection is connected from ...", conn.RemoteAddr().String())

	buf := make([]byte, 1024)
	for {
		lenght,err := conn.Read(buf)
		if checkError(err, "Connection") == false {
			conn.Close()
			break
		}
		if lenght >0 {
			buf[lenght] = 0
		}
		reciveStr := string(buf[0:lenght])
		messages <- reciveStr
	}
}

/**
客户端启动函数
参数:
    程ip地址和端口 tcpaddr
 */
func StartClient(tcpaddr string)  {
	tcpAddr,err := net.ResolveTCPAddr("tcp4", tcpaddr)
	checkError(err, "ResolveTCPAddr")
	conn,err := net.DialTCP("tcp",nil,tcpAddr)
	checkError(err, "DialTCP")

	//启动客户端发送数据线程
	go chatSend(conn)

	//接收服务端发送来的消息
	buf := make([]byte, 1024)
	for {
		lenght,err := conn.Read(buf)
		if checkError(err, "Connection") == false {
			conn.Close()
			fmt.Println("Server is dead ...ByeBye")
			os.Exit(0)
		}
		fmt.Println(string(buf[0:lenght]))
	}
}

/**
客户端发送数据线程
参数:
     发送连接 conn
 */
func chatSend(conn net.Conn)  {
	//var input string
	username := conn.LocalAddr().String()
	inputReader := bufio.NewReader(os.Stdin)
	index := 0
	for {
		//fmt.Scanln(&input)
		//这个地方改为回车结束判断,利用上面的输入检测,会有问题(不知道如何表述,就是会出现错乱)
		input, err := inputReader.ReadString('\n')
		//fmt.Fscan(stdin, &input)
		if input == "/quit" {
			fmt.Println("ByeBye..")
			conn.Close()
			os.Exit(0)
		}
		lens,err := conn.Write([]byte(username + "say ::: " + input))
		//这个地方lens不能缺省,不知道为什么
		if lens == 0 {
			//
		}
		if err != nil {
			fmt.Println(err.Error())
			conn.Close()
		}
		index++
	}
}

//错误信息
func checkError(err error, info string)  (res bool) {
	if err != nil {
		fmt.Println(info + ",err:" + err.Error())
		return false
	}
	return true
}

这个是自己做了一点修改,如果是原版的方法,客户端在字符串中添加空格的时候,那个方法scanln会自动分割空格两端的字符串,从而错乱,所以改了这个版本(就是客户端在想服务端的通道出入数据的时候的一点修改),初学炸到,不喜勿喷

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奥特曼VS怪兽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值