golang tcp入门第一个demo记录一下哈

package chat

import (
	"fmt"
	"io"
	"log"
	"net"
	"strings"
	"time"
)

var serverList map[string]net.Conn = make(map[string]net.Conn)

func Server(host string) {
	log.Printf("启动【柠檬】程序\n")
	log.Printf("server info:%s\n", host)

	server, err := net.Listen("tcp", host)
	if err != nil {
		log.Fatalf("启动聊天室服务失败:%v\n", err)
		return
	}

	for {
		conn, err := server.Accept()
		if err != nil {
			log.Fatalf("获取客户端连接失败:%v\n", err)
			continue
		}
		memberName := register(conn) //注册存储连接的信息
		if memberName != "" {
			go process(memberName)
		}

	}
}

//处理连接信息
func process(memberName string) {
	broadcastMsg("sys","【"+memberName+"】上线了") //用户上线通知
	for {
		read(memberName) //读取指定注册用户的数据
	}
}

//广播消息
func broadcastMsg(memberName string,msg string){
	for key,conn := range serverList{
		if key != memberName{
			go send(conn,memberName,msg)
		}

	}
}

//发送消息
func send(conn net.Conn,key string,msg string){

	if msg != ""{
		_,err := io.WriteString(conn,key+"("+time.Now().Format("06/01/02 15:04:05")+"): "+msg)
		if err != nil {
			fmt.Printf("向客户【%s】端广播消息失败:%v\n",key,err)
			delete(serverList,key)
			conn.Close()
		}
	}
}

//获取在线用户列表
func onlineList(memberName string){

	var onlines string
	for key,_ := range serverList{
		onlines += key
		onlines += "\n"
	}
	if onlines == "" {
		onlines = memberName+"\n"
	}
	conn,ok := serverList[memberName]
	if ok {
		_,err := io.WriteString(conn,"sys("+time.Now().Format("06/01/02 15:04:05")+"): \n"+onlines)
		if err != nil {
			fmt.Printf("向客户【%s】发送消息失败:%v\n",memberName,err)
			delete(serverList,memberName)
			conn.Close()
		}
	}

}

//从客户端读取数据
func read(memberName string) {
	var dataBuf [1024]byte //定义缓存区数据大小
	conn,ok := serverList[memberName]
	if ok {
		n, err := conn.Read(dataBuf[:])
		if err != nil && err != io.EOF {
			log.Fatalf("From %s failed:%v\n", err, conn.RemoteAddr().String())
			delete(serverList,memberName)
		}else {
			msg := string(dataBuf[:n])
			if  msg == "#quit"{
				log.Printf("%s 退出了聊天室\n",memberName)
				broadcastMsg("sys","【"+memberName+"】退出了聊天室")
				conn.Close()
				delete(serverList,memberName)
				return
			} else if msg == "#list"{
				onlineList(memberName)
			}

			if msg != "" {
				broadcastMsg(memberName,msg) //广播消息
				log.Printf("【%s】from %s >> %s\n", memberName, conn.RemoteAddr().String(), msg)
			}
		}
	}
}

//注册客户端信息
func register(conn net.Conn) string {
	var memberName string
	var buf [1024]byte
	count, err := conn.Read(buf[:])
	if err != nil {
		log.Fatalf("获取客户端注册失败:%v\n", err)
		conn.Close()
		return ""
	}
	memberName = strings.TrimSpace(string(buf[:count]))
	if memberName != "" {
		_, ok := serverList[memberName]
		if !ok {
			log.Printf("注册成功信息【%s】%s\n", memberName, conn.RemoteAddr().String())
			serverList[memberName] = conn
			_, _ = io.WriteString(conn, "1")
		} else {
			log.Printf("注册信息已经存在【%s】%s\n", memberName, conn.RemoteAddr().String())
			_, _ = io.WriteString(conn, "2")
		}
	}
	return memberName
}

package chat

import(
	"bufio"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"strings"
	"sync"
	"time"
)
var wg sync.WaitGroup
var registerName string
func sendRegister(reader *bufio.Reader,client net.Conn) bool{
	//向服务器发送注册名
	fmt.Print("注册名: ")
	name,err := reader.ReadString('\n')
	registerName = name
	registerName = strings.Replace(registerName,"\n","",-1)
	if err != nil {
		log.Fatalf("获取注册名失败:%v,请重新登录注册",err)
		return false
	}
	_,_ = io.WriteString(client,strings.TrimSpace(registerName))
	//获取返回状态
	var buf [256]byte
	n,err := client.Read(buf[:])
	if err != nil {
		log.Fatalf("获取服务器注册返回状态失败:%v\n",err)
		return false
	}
	codeStr := string(buf[:n])
	if codeStr == "1"{
		fmt.Printf("【%s】注册成功\n",registerName)
		return true
	} else if codeStr == "2"{
		fmt.Printf("【%s】注册信息已经存在,请重新选择一个名称来注册\n",registerName)
		return false
	}
	return false
}

func receiveMsg(conn net.Conn){
	defer  wg.Done()
	for{
		var buf [512]byte
		n,err := conn.Read(buf[:])
		if err != nil && io.EOF != err {
			log.Fatalf("从服务器读取消息失败:%v\n",err)
			conn.Close()
			wg.Done()
		}
		msg := string(buf[:n])
		if msg != ""{
			fmt.Printf("\n%s\n",msg)
			fmt.Printf("%s: ",registerName)
		}
	}
}



func inputMsg(client net.Conn,reader *bufio.Reader){
	defer wg.Done()
	for{
		//从控制读取数据
		consMsg,err := reader.ReadString('\n')
		consMsg = strings.Replace(consMsg,"\n","",-1)
		_,err = io.WriteString(client,consMsg)
		if err != nil {
			wg.Done()
			log.Fatalf("向服务器发送消息失败:%v\n",err)
		}else {
			fmt.Printf("%s: ",registerName)
		}
		if consMsg == "#quit"{
			fmt.Println("退出聊室")
			client.Close()
		}
	}
}


func Client(host string){

	log.Printf("与【柠檬】聊天室建立连接")
	log.Printf("服务器信息:%s\n",host)

	client,err := net.Dial("tcp",host)
	if err != nil {
		log.Fatalf("与服务器建立连接失败:%v\n",err)
		client.Close()
		return
	}

	wg.Add(2)
	reader := bufio.NewReader(os.Stdin)
	if ! sendRegister(reader,client) {
		return
	}

	time.Sleep(5*time.Second)

	time.Sleep(500*time.Millisecond)
	fmt.Printf("%s: ",registerName)
	go inputMsg(client,reader)
	time.Sleep(500*time.Millisecond)
	go receiveMsg(client)
	wg.Wait()

}
测试结果
go run ServerMain.go 
2020/04/22 14:54:34 启动【柠檬】程序
2020/04/22 14:54:34 server info:0.0.0.0:60007
2020/04/22 14:56:47 注册成功信息【tom】127.0.0.1:49745
2020/04/22 14:57:59 注册成功信息【lisa】127.0.0.1:49758
2020/04/22 14:58:56 注册成功信息【yu】127.0.0.1:49769


2020/04/22 14:56:32 与【柠檬】聊天室建立连接
2020/04/22 14:56:32 服务器信息:127.0.0.1:60007
注册名: tom
【tom】注册成功
tom: 
sys(20/04/22 14:56:47): 【tom】上线了
tom: 
sys(20/04/22 14:57:59): 【lisa】上线了
tom: 
sys(20/04/22 14:58:56): 【yu】上线了
tom


Jackm1688sMacBook-Air:chatMain JackMeng$ go run ClientMain.go 
2020/04/22 14:57:50 与【柠檬】聊天室建立连接
2020/04/22 14:57:50 服务器信息:127.0.0.1:60007
注册名: lisa
【lisa】注册成功
lisa: 
sys(20/04/22 14:57:59): 【lisa】上线了
lisa:   
sys(20/04/22 14:58:56): 【yu】上线了
lisa: #list
lisa: 
sys(20/04/22 15:05:14): 
tom
lisa
yu

lisa:
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值