簡單聊天室——伺服器
什麼是簡單聊天室?什麼又是伺服器?相對應的,什麼又是客戶端?
伺服器&客戶端,伺服器將之比作移動公司,而我們的手機就是客戶端。我們打**,就是向伺服器申請通話請求,伺服器在根據請求作出應答,即連線另一部手機,使之進行通話連線。
在計算機中,我們可以根據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...