




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第300行代碼實(shí)現(xiàn)go語(yǔ)言即時(shí)通訊聊天室學(xué)了2年Java,因?yàn)楣ぷ髟蛐枰D(zhuǎn)Golang,3天時(shí)間學(xué)習(xí)了下go的基本語(yǔ)法,做這樣一個(gè)聊天室小項(xiàng)目來(lái)鞏固串聯(lián)一下語(yǔ)法。
實(shí)現(xiàn)的功能:公聊,私聊,修改用戶名
只用到了四個(gè)類:
main.go:用來(lái)啟動(dòng)服務(wù)器server.go:服務(wù)器相關(guān)代碼client.go:客戶端相關(guān)代碼,用戶可以直接操作的可視化界面user.go:用戶類,用來(lái)封裝用戶的業(yè)務(wù)邏輯
架構(gòu)圖
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è)務(wù)邏輯
//fmt.Println("鏈接建立成功")
user:=NewUser(conn,s)
user.Online()
//監(jiān)聽(tīng)用戶是否活躍
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:
//當(dāng)前用戶活躍,不做任何時(shí),激活select,重置定時(shí)器
case-time.After(time.Second*300):
//超時(shí),將user強(qiáng)制關(guān)閉
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("請(qǐng)輸入合法數(shù)字")
returnfalse
//修改用戶名
func(c*Client)UpdateName()bool{
fmt.Println("請(qǐng)輸入用戶名")
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("請(qǐng)輸入聊天內(nèi)容,輸入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("請(qǐng)輸入聊天內(nèi)容,輸入exit退出")
fmt.Scanln(chatMsg)
func(c*Client)PrivateChat(){
varremoteUserstring
varchatMsgstring
c.SelectUsers()
fmt.Println("請(qǐng)輸入聊天對(duì)象的用戶名,輸入exit退出")
fmt.Scanln(remoteUser)
forremoteUser!="exit"{
fmt.Println("請(qǐng)輸入聊天內(nèi)容,輸入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("請(qǐng)輸入聊天內(nèi)容,輸入exit退出")
fmt.Scanln(chatMsg)
c.SelectUsers()
remoteUser=""
fmt.Println("請(qǐng)輸入聊天對(duì)象的用戶名,輸入exit退出")
fmt.Scanln(remoteUser)
//查詢?cè)诰€用戶
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","","設(shè)置服務(wù)器IP地址(默認(rèn)為)")
flag.IntVar(serverPort,"port",8888,"設(shè)置服務(wù)器端口(默認(rèn)為8888)")
funcmain(){
flag.Parse()
client:=NewClient(serverIp,serverPort)
ifclient==nil{
fmt.Println("鏈接服務(wù)器失敗")
return
goclient.DealResponse()
fmt.Println("鏈接服務(wù)器成功")
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,"下線")
//給當(dāng)前user的客戶端發(fā)送消息
func(u*User)SendMsg(msgstring){
u.conn.Write([]byte(msg))
//處理消息
func(u*User)DoMessage(msgstring){
ifmsg=="who"{
//查詢當(dāng)前在線用戶
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]
//判斷名字是否已經(jīng)存在
_,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. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 轉(zhuǎn)讓西班牙酒店協(xié)議書
- 納濾膜在乳制品加工中的應(yīng)用行業(yè)跨境出海項(xiàng)目商業(yè)計(jì)劃書
- 股票抵債務(wù)協(xié)議書
- 高端石材浴缸定制行業(yè)深度調(diào)研及發(fā)展項(xiàng)目商業(yè)計(jì)劃書
- 物流園區(qū)智能化改造企業(yè)制定與實(shí)施新質(zhì)生產(chǎn)力項(xiàng)目商業(yè)計(jì)劃書
- 創(chuàng)意廣告設(shè)計(jì)展覽企業(yè)制定與實(shí)施新質(zhì)生產(chǎn)力項(xiàng)目商業(yè)計(jì)劃書
- 高清攝影機(jī)高速拍攝企業(yè)制定與實(shí)施新質(zhì)生產(chǎn)力項(xiàng)目商業(yè)計(jì)劃書
- 高硼硅陶瓷湯鍋行業(yè)跨境出海項(xiàng)目商業(yè)計(jì)劃書
- 學(xué)生黨戀愛(ài)協(xié)議書
- 高效能晶圓清洗與干燥工藝企業(yè)制定與實(shí)施新質(zhì)生產(chǎn)力項(xiàng)目商業(yè)計(jì)劃書
- 2025-2030年中國(guó)銅合金散熱器材料行業(yè)市場(chǎng)現(xiàn)狀供需分析及投資評(píng)估規(guī)劃分析研究報(bào)告
- 醫(yī)療器械銷售流程與技巧
- 黑龍江省農(nóng)村信用社聯(lián)合社員工招聘考試真題2024
- 中華人民共和國(guó)學(xué)前教育法
- GB/T 13912-2020金屬覆蓋層鋼鐵制件熱浸鍍鋅層技術(shù)要求及試驗(yàn)方法
- 《新能源材料與器件》教學(xué)課件-04電化學(xué)能源材料與器件
- DB13T 2770-2018 焊接熔深檢測(cè)方法
- JJF 1343-2022 標(biāo)準(zhǔn)物質(zhì)的定值及均勻性、穩(wěn)定性評(píng)估
- 民法典侵權(quán)責(zé)任編課件
- 邊坡復(fù)綠專項(xiàng)施工方案
- 幼兒園課件——《生氣蟲飛上天》PPT課件
評(píng)論
0/150
提交評(píng)論