




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第300行代碼實現(xiàn)go語言即時通訊聊天室學了2年Java,因為工作原因需要轉Golang,3天時間學習了下go的基本語法,做這樣一個聊天室小項目來鞏固串聯(lián)一下語法。
實現(xiàn)的功能:公聊,私聊,修改用戶名
只用到了四個類:
main.go:用來啟動服務器server.go:服務器相關代碼client.go:客戶端相關代碼,用戶可以直接操作的可視化界面user.go:用戶類,用來封裝用戶的業(yè)務邏輯
架構圖
server.go
packagemain
import(
"fmt"
"io"
"net"
"sync"
"time"
typeServerstruct{
Ipstring
Portint
//在線用戶列表
OnlineMapmap[string]*User
mapLocksync.RWMutex
//消息廣播的Channel
Messagechanstring
funcNewServer(ipstring,portint)*Server{
server:=Server{
Ip:ip,
Port:port,
OnlineMap:make(map[string]*User),
Message:make(chanstring),
returnserver
func(s*Server)Handler(connnet.Conn){
//業(yè)務邏輯
//fmt.Println("鏈接建立成功")
user:=NewUser(conn,s)
user.Online()
//監(jiān)聽用戶是否活躍
isLive:=make(chanbool)
gofunc(){
buf:=make([]byte,4096)
for{
n,error:=conn.Read(buf)
ifn==0{
user.Offline()
return
iferror!=nilerror!=io.EOF{
fmt.Println("readerror")
msg:=string(buf[:n-1])
user.DoMessage(msg)
//表示用戶活躍
isLive-true
for{
select{
case-isLive:
//當前用戶活躍,不做任何時,激活select,重置定時器
case-time.After(time.Second*300):
//超時,將user強制關閉
user.SendMsg("你被踢了")
close(user.C)
conn.Close()
return
func(s*Server)ListenMessager(){
for{
msg:=-s.Message
s.mapLock.Lock()
for_,user:=ranges.OnlineMap{
user.C-msg
s.mapLock.Unlock()
func(s*Server)BroadCast(user*User,msgstring){
sendMsg:="["+user.Addr+"]"+user.Name+":"+msg
s.Message-sendMsg
func(s*Server)Start(){
listener,error:=net.Listen("tcp",fmt.Sprintf("%s:%d",s.Ip,s.Port))
iferror!=nil{
fmt.Println("listenererror...")
return
deferlistener.Close()
gos.ListenMessager()
for{
conn,error:=listener.Accept()
iferror!=nil{
fmt.Println("accepterror...")
continue
gos.Handler(conn)
client.go
packagemain
import(
"flag"
"fmt"
"io"
"net"
"os"
typeClientstruct{
ServerIpstring
ServerPortint
Namestring
connnet.Conn
flagint
funcNewClient(serverIpstring,serverPortint)*Client{
client:=Client{
ServerIp:serverIp,
ServerPort:serverPort,
flag:9999,
conn,error:=net.Dial("tcp",fmt.Sprintf("%s:%d",serverIp,serverPort))
iferror!=nil{
fmt.Println("netdialerror...")
returnnil
client.conn=conn
returnclient
func(c*Client)menu()bool{
varflagint
fmt.Println("1.公聊模式")
fmt.Println("2.私聊模式")
fmt.Println("3.修改用戶名")
fmt.Println("0.退出")
fmt.Scanln(flag)
ifflag=0flag=3{
c.flag=flag
returntrue
}else{
fmt.Println("請輸入合法數(shù)字")
returnfalse
//修改用戶名
func(c*Client)UpdateName()bool{
fmt.Println("請輸入用戶名")
fmt.Scanln(c.Name)
sendMsg:="rename|"+c.Name+"\n"
_,error:=c.conn.Write([]byte(sendMsg))
iferror!=nil{
fmt.Println("conn.writeerror...")
returnfalse
returntrue
func(c*Client)PublicChat(){
varchatMsgstring
fmt.Println("請輸入聊天內容,輸入exit退出")
fmt.Scanln(chatMsg)
forchatMsg!="exit"{
iflen(chatMsg)!=0{
msg:=chatMsg+"\n"
_,error:=c.conn.Write([]byte(msg))
iferror!=nil{
fmt.Println("conn.Writeerror....")
break
chatMsg=""
fmt.Println("請輸入聊天內容,輸入exit退出")
fmt.Scanln(chatMsg)
func(c*Client)PrivateChat(){
varremoteUserstring
varchatMsgstring
c.SelectUsers()
fmt.Println("請輸入聊天對象的用戶名,輸入exit退出")
fmt.Scanln(remoteUser)
forremoteUser!="exit"{
fmt.Println("請輸入聊天內容,輸入exit退出")
fmt.Scanln(chatMsg)
forchatMsg!="exit"{
iflen(chatMsg)!=0{
msg:="to|"+remoteUser+"|"+chatMsg+"\n\n"
_,error:=c.conn.Write([]byte(msg))
iferror!=nil{
fmt.Println("conn.Writeerror....")
break
chatMsg=""
fmt.Println("請輸入聊天內容,輸入exit退出")
fmt.Scanln(chatMsg)
c.SelectUsers()
remoteUser=""
fmt.Println("請輸入聊天對象的用戶名,輸入exit退出")
fmt.Scanln(remoteUser)
//查詢在線用戶
func(c*Client)SelectUsers(){
sendMsg:="who\n"
_,error:=c.conn.Write([]byte(sendMsg))
iferror!=nil{
fmt.Println("conn.Writeerror....")
return
//處理server返回的消息
func(c*Client)DealResponse(){
io.Copy(os.Stdout,c.conn)
func(c*Client)Run(){
forc.flag!=0{
forc.menu()!=true{
switchc.flag{
case1:
//公聊
c.PublicChat()
case2:
//私聊
c.PrivateChat()
case3:
//修改用戶名
c.UpdateName()
varserverIpstring
varserverPortint
funcinit(){
flag.StringVar(serverIp,"ip","","設置服務器IP地址(默認為)")
flag.IntVar(serverPort,"port",8888,"設置服務器端口(默認為8888)")
funcmain(){
flag.Parse()
client:=NewClient(serverIp,serverPort)
ifclient==nil{
fmt.Println("鏈接服務器失敗")
return
goclient.DealResponse()
fmt.Println("鏈接服務器成功")
client.Run()
user.go
packagemain
import(
"net"
"strings"
typeUserstruct{
Namestring
Addrstring
Cchanstring
connnet.Conn
server*Server
funcNewUser(connnet.Conn,server*Server)*User{
userAddr:=conn.RemoteAddr().String()
user:=User{
Name:userAddr,
Addr:userAddr,
C:make(chanstring),
conn:conn,
server:server,
gouser.ListenMessage()
returnuser
//用戶上線
func(u*User)Online(){
u.server.mapLock.Lock()
u.server.OnlineMap[u.Name]=u
u.server.mapLock.Unlock()
u.server.BroadCast(u,"上線")
//用戶下線
func(u*User)Offline(){
u.server.mapLock.Lock()
delete(u.server.OnlineMap,u.Name)
u.server.mapLock.Unlock()
u.server.BroadCast(u,"下線")
//給當前user的客戶端發(fā)送消息
func(u*User)SendMsg(msgstring){
u.conn.Write([]byte(msg))
//處理消息
func(u*User)DoMessage(msgstring){
ifmsg=="who"{
//查詢當前在線用戶
u.server.mapLock.Lock()
for_,user:=rangeu.server.OnlineMap{
onlineMsg:="["+user.Addr+"]"+user.Name+":在線...\n"
u.SendMsg(onlineMsg)
u.server.mapLock.Unlock()
}elseiflen(msg)7msg[:7]=="rename|"{
//修改用戶名rename|xxx
newName:=strings.Split(msg,"|")[1]
//判斷名字是否已經存在
_,ok:=u.server.OnlineMap[newName]
ifok{
u.SendMsg("用戶名已存在\n")
}else{
u.server.mapLock.Lock()
delete(u.server.OnlineMap,u.Name)
u.server.OnlineMap[newName]=u
u.server.mapLock.Unlock()
u.Name=newName
u.SendMsg
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年抗肝片吸蟲病藥項目資金申請報告代可行性研究報告
- 浙江省錢塘聯(lián)盟2024-2025學年高一下學期4月期中聯(lián)考試題 地理 PDF版含答案
- 醫(yī)療實驗室標準化管理的關鍵要素
- 線粒體腦肌病的臨床護理
- 三通訂貨合同范例
- 從全球化到數(shù)字化探索未來商業(yè)的基石-區(qū)塊鏈技術
- 個人競業(yè)合同范例
- 小兒原發(fā)性腦干損傷的臨床護理
- mv拍攝合同范例
- 伊犁勞動合同范例
- 執(zhí)法辦案和執(zhí)法監(jiān)督注意事項課件
- 客運駕駛人從業(yè)行為定期考核制度
- 《新能源材料與器件》教學課件-04電化學能源材料與器件
- 2022年同等學力人員申請碩士學位日語水平統(tǒng)一考試真題
- 城軌道交通人因事故分析及評價研究
- T∕CADERM 2002-2018 胸痛中心(基層版)建設與評估標準
- ZYWL-4000型履帶式鉆機
- 50MPa路面抗折混凝土配合比
- 油閥座加工工藝與夾具設計說明
- 護士壓力與情緒管理PPT課件
- 劉鴻文材料力學習題集(全且附有標準答案)
評論
0/150
提交評論