簡單聊天室 總述

2021-08-31 08:20:29 字數 4741 閱讀 8282

簡單聊天室——伺服器

什麼是簡單聊天室?什麼又是伺服器?相對應的,什麼又是客戶端?

伺服器&客戶端,伺服器將之比作移動公司,而我們的手機就是客戶端。我們打**,就是向伺服器申請通話請求,伺服器在根據請求作出應答,即連線另一部手機,使之進行通話連線。

在計算機中,我們可以根據ip和埠建立伺服器:

1. 獲得ip

在命令提示符中,輸入ipconfig,從中獲得ipv4即可。下列都用本地ip  localhost。

2. 建立埠

埠一般是從0~2^16之間,前1024個埠為常用埠,有特殊用途,比如80埠,故只用後面的一些埠。

下列中皆選取9999埠。

3. 建立伺服器(等待客戶端接入)

/**

* 建立乙個伺服器

* * @param port:埠號

* @throws ioexception

*/public void setupserver(int port) throws ioexception

}

藍色部分便是建立乙個伺服器,只傳入埠號即可。

紅色部分"color: #ff0000">,在計算機中,其實乙個埠只能連線上乙個程序,換句話講,乙個伺服器只能連線乙個客戶端,這顯然不是我們想要的,故將客戶端設定為執行緒,用乙個近似於死迴圈,等待乙個個客戶端的接入,將socket物件傳入到自定義的客戶端執行緒類中即可操作該客戶端,其中乙個客戶端對應乙個客戶端執行緒,當沒有客戶端接入時,伺服器進入阻塞。 

只要在主函式中呼叫setupserver(port)方法,乙個簡單的伺服器&客戶端就完成了,只不過他還不能幹任何事。

下面講講伺服器&客戶端都需要幹些什麼:

一. 伺服器類:

1. clientthread類  對應客戶端的執行緒,每乙個客戶端接入就會建立乙個該執行緒,而將執行緒放入佇列中,就是乙個使用者執行緒佇列,其中定義了方法(引數省略):

⑴. getoweruser()  取得該執行緒的使用者物件(userinfor類的物件)

⑵. closeme()          關閉該執行緒

⑶. setmessage()    傳送給客戶端(用到輸出流out.write())

⑷. readstring()      自定義的對客戶端發來的資訊的讀取(用到輸入流ins.read()) 

⑸. dealmsg()          處理從客戶端發來的資訊(有關對通訊協議xmpp的處理)(完成了登陸應答,註冊應答等等)

public void run()  catch (ioexception e) 

}public void threadmain() throws ioexception while (!isclose);

}

該類中的主要方法,紅色部分"color: #ff0000"

>,是乙個近似的死迴圈,他的作用是不停的從socket物件client中讀取,如果沒有則阻塞,這與客戶端連線伺服器相似。

2. userinfor類  使用者物件的類,在簡單聊天室中,只有使用者名稱和密碼兩個屬性,設定&獲取 四個方法。

3. servertools類  伺服器的工具類,定義了靜態的方法,將每個clientthread的物件放入到乙個佇列中,即有對應的方法addthread(),remove(),clear(),getnum()(佇列中元素個數)等方法,其中將所有執行緒物件放在乙個佇列中,就可以根據需求對每乙個執行緒進行操作,實現**資訊。

4.daotools類  不同於 servertools類

5. serverui類&serverlistener類  介面的類和***的類。

二. 客戶端類

客戶端和伺服器是不同的兩個程式,即有兩個主函式,而連線客戶端與伺服器的紐帶就是ip和埠。

1. clientui類 客戶端的介面類。

2. clienttx類 客戶端的通訊類。

⑴. con2server()  建立乙個客戶端連線上伺服器。

/**

* 1.是否連線上伺服器

*/public boolean con2server() catch (exception ef)

return false;

}

紅色部分"color: #ff0000"

>,在客戶端中穿件socket物件不同於在伺服器中建立,這裡需要傳入ip位址和埠,注意serverip

在這裡是乙個string,要輸入比如"192.168.1.150"或者"localhost"本地ip;

⑵. loginserver(string name,string pwd)  傳送登陸的使用者名稱和密碼給伺服器,伺服器驗證後傳回訊息。

⑶. chatonline()  主要的聊天方法。

/**

* 執行緒中讀取伺服器發來的訊息

*/public void run()

/** * 3.開始聊天 (1).獲取資訊,寫在jta_main上

*/public void chatonline() while (!isclose);

} catch (ioexception e)

}

紅色部分"color: #ff0000"

>,不斷讀取流中的資訊,然後反映到jtextarea的物件上。

⑷. readstring()  自定義的對客戶端發來的資訊的讀取(用到輸入流ins.read()) 

⑸. dealmsg()   處理從伺服器發來的資訊(有關對通訊協議xmpp的處理)(完成了登陸結果,註冊結果等等)

三. xmpp

根據xmpp自定義了一套傳輸的協議。

1. 登陸請求 "" + name + "

" + pwd + "

"2. 登陸應答 "no name

"3. 註冊請求 "" + yhm + "

" + mm + "

"4. 註冊應答 "" + isregister + "

"(isregister是daotools中的乙個靜態方法

isregister()的返回值,boolean)

5. 資訊傳送 "" + uname  + "

" + " 大家 " + "

" +

content_next + "

"6. 下線請求 "" + uname + "

"7. readstring(inputstream ins)

/**

* 自定義的讀取字串的方法 從輸入流上讀取位元組,轉為乙個字串,以分割

* * @param ins:輸入流物件

* @return:讀取到的字串

* @throws ioexception

*/private void readstring(inputstream ins) throws ioexception

// 中文解析

input2 = new string(sb.tostring().getbytes("iso-8859-1"), "gbk").trim();

dealmsg(input2);

}

8. dealmsg(string msg)——伺服器

/**

* 處理資訊

* * @param msg:傳入的內容

* @throws ioexception

*/public void dealmsg(string msg) throws ioexception else if (islogin) else

// 新增執行緒

if (!islogin && loginstate)

} // 訊息內容

else if (msg.startswith(""))

// 註冊應答

else if (msg.startswith(""))

// 下線應答

else if (msg.startswith(""))

}

9. dealmsg(string msg)——客戶端

/**

* 處理資訊

* * @param msg:傳入的內容

*/private string dealmsg(string msg)

// 訊息內容

else if (msg.startswith(""))

// 註冊資訊

else if (msg.startswith(""))

return output;

}

四. 問題總結

1. 對於 客戶端接入 與 註冊登陸 先後順序問題。在登陸介面中,我們需要將登陸資訊傳送的伺服器,在註冊介面中,我們也需要傳送註冊資訊。註冊 和 登陸 在操作時,不分先後,這就要求我們不能將 客戶端的接入只寫在登陸介面或註冊介面,當然也不能兩個都寫,可以寫在介面生成之前,如果伺服器未開啟,則不顯示登陸介面。否則 會報空指標異常(socket物件client為空,ins,out輸入輸出流物件也為空)。

3. 關於 使用者列表 的讀取寫入問題。在 註冊時 我們需要將使用者的資訊寫入到乙個檔案中,使用者名稱可以是中文,在開啟伺服器時,要讀取檔案中的資訊,這樣使用者在註冊一次後就可以一直用這個賬號登陸,而不用每次開啟伺服器就要註冊一遍。

我在寫入時用的是writeutf()的方法,讀取時用readutf()的方法,如果用write(byte b)或者writebyte(byte b),read(byte b)或者readfully(byte b)等方法,會報空指標,原因不懂,希望有人能幫我解決一下。

簡單聊天室

include include include include include include include include include include pthread t thread 2 void send msg void ip msg if connect sockfd,struct ...

Linux UDP簡單聊天室

伺服器端 include include include include include include include include int sockfd 0 建立結構體用來存放客戶端資訊 typedef struct node node t node t link head node t h ...

go 簡單聊天室

package main import fmt net strings time 建立使用者結構體型別 type cline struct var onlinemap map string cline 建立全域性 channel 傳遞使用者訊息 var message make chan strin...