如何從零開始寫一個即時通訊軟體(附原始碼)

qq_27311165發表於2017-07-25

       即時通訊,即傳送了訊息後對方馬上收到,一般用tcp或者udp協議來傳輸訊息。我也是第一次深入學習tcp和udp的使用,編碼過程中遇到很多難題,自己辛辛苦苦百度,解決了一個又一個困難,但是個人的聽聞是有限的,希望能拋磚引玉,聽取到大家更好的解決辦法。

       專案地址:http://download.csdn.net/detail/qq_27311165/9911099

       首先,這個專案的伺服器大部分bean用Spring來託管,Spring託管了專案的dao層和業務層(QQService)還有helper模組(UDPHelper、TCPConnectionManager這兩個單例),而且都是單例。單例就可能牽扯到執行緒安全問題,dao都是單例,jdbc中,如果多個執行緒同時執行靜態方法DriverManager.getConnection()會丟擲異常,所以將該靜態方法封裝到DBHelper的getConnection()方法中,加上synchronized使執行緒同步,因為dao的方法除了dbHelper.getConnection();外其他都是訪問區域性變數和引數,每個執行緒呼叫dao的方法時都有自己的區域性變數和引數,所以dao現在是執行緒安全的。伺服器其他部分經過我不停地取證,應該也是執行緒安全的。             客戶端,因為我想急於驗證它和伺服器的通訊,所以寫得非常簡便。客戶端讀者也可以用另外的語言編寫,只要傳送的tcp和udp報文能被伺服器解析(“報文規定.txt”已經在壓縮包中)。

       資料庫只有3張表user、friend、unreadmsg。

CREATE TABLE user(
   userid            INT(8)            PRIMARY KEY        AUTO_INCREMENT,
   username            VARCHAR(20)    NOT NULL        unique,
   password            VARCHAR(20)    NOT NULL,
   isonline            boolean        NOT NULL,
   
    nickname        VARCHAR(20)    NOT NULL,            #暱稱,網名
    sex                VARCHAR(4),
    birthday        DATE,
    hometown        VARCHAR(20),
    livein            VARCHAR(20),
    motto            VARCHAR(100)                    #座右銘,個性簽名
) ;
CREATE TABLE friend(
    id                INT(20)            PRIMARY KEY        AUTO_INCREMENT,
   username            VARCHAR(20)    NOT NULL,
   friendname        VARCHAR(20)    NOT NULL,
   friendnickname        VARCHAR(20)    NOT NULL,
   fgroup            VARCHAR(20)    NOT NULL,            #好友分組名,可以一個好友一個組
   note                VARCHAR(20)        #好友備註
) ;
CREATE TABLE unreadmsg(        #只有未讀訊息才有資格存進資料庫
    id                INT(20)            PRIMARY KEY        AUTO_INCREMENT,
   sendername        VARCHAR(20)        NOT NULL,
   receivername        VARCHAR(20)        NOT NULL,
   msgtype            int(4)            NOT NULL,
   sendtime            VARCHAR(25)        NOT NULL,            #傳送者傳送到伺服器時,伺服器把當前時間賦給它
   msg                VARCHAR(200)    NOT NULL
) ;

        先來分析一下即時通訊軟體,什麼資料要被存到資料庫,使用者的資訊肯定是要存到資料庫的,所以有了user表,使用者肯定要有自己的好友,friend表中username是自己的使用者名稱,後面4個欄位分別表示好友使用者名稱、好友暱稱、好友所在分組名、備註名字。就這樣,我們就可以用一條記錄表示一個好友。最後是unreadmsg,未讀訊息,如果好友不線上,就先把訊息存到資料庫,等好友上線後,伺服器從資料取出訊息發給好友。

        目前伺服器和客戶端大部分是用tcp通訊,只有發訊息給好友時才用udp通訊。為了方便使用tcp,客戶端把Socket封裝到了TCPConnection這個單例類;為了方便使用udp,客戶端把Socket封裝到了UDPHelper這個單例類。

         客戶端可以在任何地方使用
TCPConnection.getInstance().sendAndWaitResponse(String msg);    //只往伺服器發訊息,且等待迴應

TCPConnection.getInstance().justSend(String msg);               //只往伺服器發訊息,不等待迴應

UDPHelper.getInstance().send(String content);                            //只往伺服器發訊息
傳送訊息給伺服器。

          我突然不想寫了,請自己參考其中的妙處。下載完壓縮包後

請把Spring配置檔案下
        <property name="dbpassword">
            <value>xxx</value>
        </property>
的xxx改為你的資料庫密碼
請把客戶端的TCPConnection類的
    private TCPConnection() {
        try {
            client = new Socket("192.168.1.106", 8888);
            .....
"192.168.1.106"改為你伺服器的ip地址,才能正常執行。

          一個路由器就是一個區域網,已經能正常執行。qq.sql指令碼里建立6個預設使用者。目前實現的功能:聊天、聊天記錄儲存(在record目錄下儲存)、上線未讀訊息提醒。請期待後續更新。

         下面是截圖,一張是執行截圖,一張是聊天記錄檔案的截圖,你可能需要兩臺電腦登入兩個賬號才能開聊。(一臺開啟伺服器和一個客戶端,另一臺開另一個客戶端)


相關文章