go_study/bilibili/aceld/IM-System/client/client.go

195 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 客户端应用
package main
import (
"flag"
"fmt"
"io"
"net"
"os"
)
type Client struct {
ServerIp string
ServerPort int
Name string
conn net.Conn
flag int // 当前client模式
}
func NewClient(serverIp string, serverPort int) *Client {
// 创建Client对象
client := &Client{
ServerIp: serverIp,
ServerPort: serverPort,
flag: 999,
}
// 连接Server
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", serverIp, serverPort))
if err != nil {
fmt.Println("net.Dial err:", err)
return nil
}
client.conn = conn
// 返回Client对象
return client
}
func (client *Client) menu() bool {
var flag int
fmt.Println("1. 公聊模式")
fmt.Println("2. 私聊模式")
fmt.Println("3. 更新用户名")
fmt.Println("0. 退出")
fmt.Scanln(&flag)
client.flag = flag
if flag >= 0 && flag <= 3 {
return true
} else {
fmt.Println(">>>>>> 请输入合法的数字 <<<<<<")
return false
}
}
// 查询当前在线用户
func (client *Client) SelectUsers() {
sendMsg := "who\n"
_, err := client.conn.Write([]byte(sendMsg))
if err != nil {
fmt.Println("conn Write err:", err)
return
}
}
// 私聊模式处理方法
func (client *Client) PrivateChat() {
var remoteName string
var chatMsg string
// 查询当前在线用户名
client.SelectUsers()
fmt.Println(">>>>>> 请输入对方用户名, exit返回菜单")
fmt.Scanln(&remoteName)
for remoteName != "exit" {
fmt.Println(">>>>>> 请输入消息内容exit重新选择对象")
fmt.Scanln(&chatMsg)
for chatMsg != "exit" {
// 消息不为空则发送消息
if len(chatMsg) != 0 {
sendMsg := "to|" + remoteName + "|" + chatMsg + "\n\n"
_, err := client.conn.Write([]byte(sendMsg))
// 判断消息不为空则发送
if err != nil {
fmt.Println("conn Write err:", err)
break
}
}
// 清空上次输入
chatMsg = ""
fmt.Scanln(&chatMsg)
}
client.SelectUsers()
fmt.Println(">>>>>> 请输入对方用户名, exit返回菜单")
fmt.Scanln(&remoteName)
}
}
// 公聊模式处理方法
func (client *Client) PublicChat() {
// 提示用户输入消息
var chatMsg string
fmt.Println(">>>>>> 请输入群聊内容exit返回菜单")
fmt.Scanln(&chatMsg)
// 发送给服务器
for chatMsg != "exit" {
// 消息不为空则发送消息
if len(chatMsg) != 0 {
sendMsg := chatMsg + "\n"
_, err := client.conn.Write([]byte(sendMsg))
// 判断消息不为空则发送
if err != nil {
fmt.Println("conn Write err:", err)
break
}
}
// 清空上次输入
chatMsg = ""
fmt.Scanln(&chatMsg)
}
}
// client的更新用户名接口
func (client *Client) UpdateName() bool {
fmt.Println(">>>>>> 请输入新用户名:")
fmt.Scanln(&client.Name)
sendMsg := "rename|" + client.Name + "\n"
// 把sendMsg发送给server端
_, err := client.conn.Write([]byte(sendMsg))
if err != nil {
fmt.Println("conn.Write err:", err)
return false
}
return true
}
// 启动客户端服务
func (client *Client) Run() {
for client.flag != 0 {
for !client.menu() {
}
// 根据不同的模式处理不同的业务
switch client.flag {
case 1:
// 公聊模式s
client.PublicChat()
case 2:
// 私聊模式
client.PrivateChat()
case 3:
// 更新用户名
client.UpdateName()
default:
fmt.Println("无效的菜单命令")
}
}
}
// 处理server回应的消息直接显示到标准输出
func (client *Client) DealResponse() {
// 一旦client.conn有数据就直接copy到stdout标准输出上永久阻塞监听
io.Copy(os.Stdout, client.conn)
}
// 定义全局变量
var serverIp string
// 定义全局变量
var serverPort int
// init函数会在main函数之前执行
func init() {
// ./client -ip 127.0.0.1
flag.StringVar(&serverIp, "ip", "127.0.0.1", "设置服务端IP地址默认127.0.0.1")
// ./client -port 8888
flag.IntVar(&serverPort, "port", 8888, "设置服务端端口默认8888")
}
func main() {
// 解析命令行传参
flag.Parse()
client := NewClient(serverIp, serverPort)
if client == nil {
fmt.Println(">>>>>> 连接服务器失败!")
return
}
fmt.Println(">>>>>> 连接服务器成功……")
// 单独开启一个goroutine去处理server发送的消息
go client.DealResponse()
// 启动客户端服务
client.Run()
}