300行代碼實(shí)現(xiàn)go語(yǔ)言即時(shí)通訊聊天室_第1頁(yè)
300行代碼實(shí)現(xiàn)go語(yǔ)言即時(shí)通訊聊天室_第2頁(yè)
300行代碼實(shí)現(xiàn)go語(yǔ)言即時(shí)通訊聊天室_第3頁(yè)
300行代碼實(shí)現(xiàn)go語(yǔ)言即時(shí)通訊聊天室_第4頁(yè)
300行代碼實(shí)現(xiàn)go語(yǔ)言即時(shí)通訊聊天室_第5頁(yè)
已閱讀5頁(yè),還剩7頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論