基于TCP協(xié)議的簡單即時通信軟件的設(shè)計與實現(xiàn)(含源文件)_第1頁
基于TCP協(xié)議的簡單即時通信軟件的設(shè)計與實現(xiàn)(含源文件)_第2頁
基于TCP協(xié)議的簡單即時通信軟件的設(shè)計與實現(xiàn)(含源文件)_第3頁
基于TCP協(xié)議的簡單即時通信軟件的設(shè)計與實現(xiàn)(含源文件)_第4頁
基于TCP協(xié)議的簡單即時通信軟件的設(shè)計與實現(xiàn)(含源文件)_第5頁
已閱讀5頁,還剩15頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、 基于TCP協(xié)議的網(wǎng)絡(luò)通信系統(tǒng)的設(shè)計與實現(xiàn)摘  要 :網(wǎng)絡(luò)通信,由于其具有實時性、跨平臺性、成本低、效率高等優(yōu)點而受到廣泛的使用。設(shè)計并實現(xiàn)一個能夠處理多用戶進(jìn)行實時、安全的即時通信系統(tǒng)具有較強(qiáng)的現(xiàn)實意義。即時通信的底層通信是通過SOCKET套接字接口實現(xiàn)的。當(dāng)前的主流UNIX系統(tǒng)和微軟的WINDOWS系統(tǒng)都在內(nèi)核提供了對SOCKET字接口的支持。使用這個統(tǒng)一的接口,可以編寫一個可移植的TCP/IP通信程序。使信息能夠在INTERNET上可靠的傳輸。  本文設(shè)計并實現(xiàn)了基于局域網(wǎng)內(nèi)的簡單即時通信系統(tǒng),系統(tǒng)采用C/S模式,底層通信通過SOCKET套接字接口

2、實現(xiàn),服務(wù)器負(fù)責(zé)客戶端的登錄驗證,好友信息的保存和心跳報文的發(fā)送??蛻舳瞬捎肞2P方式實現(xiàn)消息傳遞,并能實現(xiàn)文件的傳輸。本文首先討論了同步套接字,異步套接字,多線程并發(fā)執(zhí)行任務(wù)等;然后闡述了客戶端、服務(wù)器如何使用XML序列化的消息進(jìn)行通信。關(guān)鍵詞:即時通信;文件傳輸;套接字;TCP協(xié)議Abstract :Instant messages have several advantages such as real-time, cross-platform, cheap and e

3、fficient. To design a Multi-user IM (instant message) architecture is very important in both theory and realism. Instant message based on TCP/IP protocol that is realized 

4、;by socket interface. Almost all UNIX operation systems and Microsoft's windows operation systems provide support of socket in the kernel. Using the uniform interface, we 

5、can develop a portable program of TCP/IP, which help us transfer information in Internet safely and credibly. The system uses the client/server(C/S) mode. The server takes

6、0;the responsibility of the login message of client, the saving of friend message and Message heartbeat. The transmission of the basic messages of the customer end will&#

7、160;be designed on P2P architecture. This thesis explains how the client and server communicate via serializing XML message.Key words:  Instant Message; File Transfer; Socket; 

8、;TCP protocol  引言 1.1  課題背景  即時通信是一個終端連往一個即時通信網(wǎng)路的服務(wù)。即時通信不同于e-mail在于它的交談是實時的。大部分的即時通信服務(wù)提供了presence awareness的特性顯示聯(lián)絡(luò)人名單,聯(lián)絡(luò)人是否在在線與能否與聯(lián)絡(luò)人交談。  最早的即時通信軟件是ICQ,ICQ是英文中I seek you的諧音,意思是我找你。四名以色列青年于1996年7月成立Mirabilis公司,并在11月份發(fā)布了最初的ICQ版本,在六個月內(nèi)有85萬用戶注冊使用。 

9、在因特網(wǎng)上受歡迎的即時通信服務(wù)包含了MSN Messenger、AOL Instant Messenger、Yahoo! Messenger、NET Messenger Service、Jabber、ICQ與QQ。 這些服務(wù)有賴于許多想法更久的(與普遍)的在線聊天媒介,如Internet Relay Chat一樣知名。 1970年代早期,一種更早的即時通信形式是柏拉圖系統(tǒng)(PLATO system)。之后在1980年代,UNIX/Linux的交談實時信息被廣泛的使用于工程師與學(xué)術(shù)界,1990年代

10、即時通信更跨越了因特網(wǎng)交流。1996年11月,ICQ是首個廣泛被非UNIX/Linux使用者用于因特網(wǎng)的即時通信軟件。在ICQ的介紹之后,同時在許多地方有一定數(shù)量的即時通信方式發(fā)展,且各式的即時通信程序有獨立的協(xié)議,無法彼此互通。這引導(dǎo)使用者同時執(zhí)行兩個以上的即時通信軟件,或者他們可以使用支持多協(xié)議的終端軟件,如Gaim、Trillian或Jabber。 1.2  國內(nèi)外研究現(xiàn)狀 1.2.1 國外研究現(xiàn)狀當(dāng)今,國際上對網(wǎng)絡(luò)通信系統(tǒng)研究的較好的公司有,思科,Sun,Ms等公司,思科主要研究的是底層的傳輸;MS,Sun公司研究的是應(yīng)用層。其中ms公

11、司憑借其在操作系統(tǒng)的壟斷地位,為了在網(wǎng)絡(luò)的發(fā)展中取得先機(jī),采用了各種各樣的手段。但是,其捆綁的msn,無論從功能上,還是技術(shù)上來說,都不算是非常先進(jìn)的。當(dāng)然,ie,同樣也不是很受人青睞,這讓人想起了,當(dāng)年的網(wǎng)景公司,網(wǎng)景只是生不逢時。MS不擇手段的想打跨網(wǎng)景,可見其對網(wǎng)絡(luò)的重視。如今,Sun公司在網(wǎng)絡(luò)應(yīng)用上捷足先登,憑借著Java,Sun在網(wǎng)絡(luò)的應(yīng)用上領(lǐng)先于MS。微軟,想用同樣的辦法搞跨對手,因此它拿出了Visual c#,來對抗Java。這些都是在應(yīng)用層面的開發(fā)工具。應(yīng)用層上的產(chǎn)品就更顯種類繁多。ICQ幾乎是國際上通用的即時通信工具,由于在我國它的應(yīng)用不是很廣,所以,其原理也很少被

12、介紹。msn,是MS的產(chǎn)品,同樣在國內(nèi)沒什么市場,所以,對其原理,也很少被討論過。至于ie,是在Visual c+下開發(fā)的產(chǎn)品,雖然有嚴(yán)重的安全隱患,不過,至少能在某種程度上代表當(dāng)今國際研究的水平。此外,國際上最近出先了新的瀏覽器Firefox,其性能據(jù)說是遠(yuǎn)高于ie,也許在網(wǎng)絡(luò)的天下,Ms又有了更強(qiáng)勁的對手。1.2.2  國內(nèi)研究現(xiàn)狀 國內(nèi)在應(yīng)用層上的網(wǎng)絡(luò)應(yīng)用軟件目前發(fā)展異常的火爆,因為我國有著網(wǎng)絡(luò)應(yīng)用的最大的市場,現(xiàn)在國內(nèi)網(wǎng)絡(luò)的基礎(chǔ)性建設(shè)發(fā)展迅速,應(yīng)用軟件也層出不窮,其中,在游戲的領(lǐng)域中,網(wǎng)絡(luò)通信的工作做的不錯,如聯(lián)眾游戲平臺,還有其他的一些平臺,這

13、些平臺基本上都是基于VC+的,用的都是Socket通信,但是為了效率,這些平臺沒有用MFC提供的CSocket類,而是直接用Socket進(jìn)行通信。所以效率上不錯。此外,tencent的即時通信,也是做的很好的,從某中程度上來說,代表了國內(nèi)最高的水平。 1.3  本課題的研究方法  本系統(tǒng)采用C/S(Client/Server)結(jié)構(gòu)進(jìn)行設(shè)計,使用SQL Server 2000構(gòu)建數(shù)據(jù)庫,并在.NET環(huán)境下使用Visual C#.net語言和SOCKET套接字開發(fā)一個基于TCP協(xié)議的簡單即時通信軟件,實現(xiàn)簡單的即時聊天,文件傳輸

14、等功能。2 相關(guān)技術(shù)介紹 2.1 .NET開發(fā)平臺及C.NET開發(fā)語言  NET框架是Microsoft公司推出的一種全新的開發(fā)平臺,提供了統(tǒng)一的、面向?qū)ο蟛⑶铱梢詳U(kuò)展的編程類庫和完善的集成開發(fā)環(huán)境,大大簡化了應(yīng)用程序的開發(fā)過程,并且具有良好的移植性和安全性。  微軟為了推行.NET戰(zhàn)略,特別為.NET平臺設(shè)計了一種語言C#。C#是由C和C+派生而來的一種“簡單、流行、面向?qū)ο?、類型安全”的程序設(shè)計語言,其綜合了Visual basic的高效率和C+的強(qiáng)大功能,然而更多的人感覺C#更類似JAVA。2.2  TCP協(xié)

15、議 2.2.1 TCP/IP網(wǎng)絡(luò)協(xié)議  協(xié)議是對等的網(wǎng)絡(luò)實體之間通信的規(guī)則,可以簡單地理解為網(wǎng)絡(luò)上各計算機(jī)彼此交流的一種“語言”。網(wǎng)絡(luò)通信協(xié)議設(shè)計的基本原則是層次化,層和協(xié)議的集合被稱為網(wǎng)絡(luò)體系結(jié)構(gòu)。相鄰層之間的接口定義了下層向上層提供的基本操作和服務(wù),下層向上層提供的服務(wù)分兩種形式:面向連接的服務(wù)和無連接的服務(wù)。  計算機(jī)網(wǎng)絡(luò)中已經(jīng)形成的網(wǎng)絡(luò)體系結(jié)構(gòu)主要有兩個:OSI參考模型和TCP/IP參考模型。TCP/IP參考模型是因特網(wǎng)(Internet)的基礎(chǔ)。和OSI的7層協(xié)議相比,TCP/IP協(xié)議只有4個層次。通常說的TCP/IP是一組協(xié)議的總稱,TCP/

16、IP實際上是一個協(xié)議族,包括100多個相互關(guān)聯(lián)的協(xié)議,其中IP(Internet Protocol, 網(wǎng)際協(xié)議)是網(wǎng)絡(luò)層最主要的協(xié)議;TCP(Transmission Control Protocol,傳輸控制協(xié)議)和UDP(User Datagram Protocol,用戶數(shù)據(jù)報協(xié)議是傳輸層中最主要的協(xié)議),一般認(rèn)為IP、TCP、UDP是最根本的三種協(xié)議,是其他協(xié)議的基礎(chǔ)。2.2.2 TCP傳輸控制協(xié)議 :面向連接的通信可以使用可靠通信,在這時候,第四層協(xié)議發(fā)送數(shù)據(jù)接收方的確認(rèn),如果未收到數(shù)據(jù)或者數(shù)據(jù)被損壞,則請

17、求重新傳輸。TCP協(xié)議就使用這種可靠通信。 使用TCP協(xié)議的應(yīng)用層協(xié)議包括HTTP、FTP、SMTP和Telnet等。   現(xiàn)在可以發(fā)送和接收消息了。接收消息后,總是返回ACK消息。如果在收到ACK之前發(fā)送方已經(jīng)超時,則消息將被放到重發(fā)隊列中以再次發(fā)送。  由于它的握手機(jī)制,所以TCP協(xié)議比較復(fù)雜并且費時,但此協(xié)議在處理數(shù)據(jù)時對數(shù)據(jù)包的傳送有保障,從而使得在應(yīng)用程序協(xié)議中不需要再包括該功能。2.3 套接字  套接字這個術(shù)語并沒有定義某個協(xié)議:它具有兩層含義,但兩者都與一個協(xié)議相關(guān)。第一個含義是套接字編程API,它最初由伯克利大學(xué)為BS

18、D UNIX而創(chuàng)建。BSD套接字在經(jīng)過修改后被用作Windows環(huán)境的編程接口(并且被命名為WinSock)。WinSock API被包裝在System.Net.sockets命名空間的.NET類中。Windows Sockets 是一個獨立于協(xié)議的編程接口,用于編寫網(wǎng)絡(luò)應(yīng)用程序。 2.4 流 2.4.1 流的基本概念 流的概念已經(jīng)存在很長時間了。流是一個用于傳輸數(shù)據(jù)的對象。數(shù)據(jù)的傳輸有兩個方向:  1)如果數(shù)據(jù)從外部源傳輸?shù)匠绦蛑?,這就是讀取流。 2) 如果數(shù)據(jù)從程序傳輸?shù)?/p>

19、外部源,這就是寫入流。 外部源常常是一個文件,但也不完全都是文件,它還可以是: 1) 網(wǎng)絡(luò),使用一定的網(wǎng)絡(luò)協(xié)議與網(wǎng)絡(luò)上其它計算機(jī)或終端交換數(shù)據(jù)。 2) 一個指定的管道。 3) 一塊內(nèi)存區(qū)域。2.5 同步、異步、阻塞和非阻塞   同步(synchronous):所謂同步方式,就是發(fā)送方發(fā)送數(shù)據(jù)包以后,不等接受方響應(yīng),就接著發(fā)送下一個數(shù)據(jù)包。  異步(asynchronous):異步方式就是當(dāng)發(fā)送方發(fā)送一個數(shù)據(jù)包以后,一直等到接受方響應(yīng)后,才接著發(fā)送下一個數(shù)據(jù)包。  阻塞(Block):指執(zhí)行此套接字的網(wǎng)絡(luò)調(diào)

20、用時,直到調(diào)用成功才返回,否則此套節(jié)字就一直阻塞在網(wǎng)絡(luò)調(diào)用上,比如調(diào)用StreamReader 類的Readlin ( )方法讀取網(wǎng)絡(luò)緩沖區(qū)中的數(shù)據(jù),如果調(diào)用的時候沒有數(shù)據(jù)到達(dá),那么此Readlin ( )方法將一直掛在調(diào)用上,直到讀到一些數(shù)據(jù),此函數(shù)調(diào)用才返回。 非阻塞(Unblock):指在執(zhí)行此套接字的網(wǎng)絡(luò)調(diào)用時,不管是否執(zhí)行成功,都立即返回。同樣調(diào)用StreamReader 類的Readlin ( )方法讀取網(wǎng)絡(luò)緩沖區(qū)中數(shù)據(jù),不管是否讀到數(shù)據(jù)都立即返回,而不會一直掛在此函數(shù)調(diào)用上。  在Windo

21、ws網(wǎng)絡(luò)通信軟件開發(fā)中,最為常用的方法就是異步非阻塞套接字。平常所說的C/S(客戶端/服務(wù)器)結(jié)構(gòu)的軟件采用的方式就是異步非阻塞模式的。  其實在用C進(jìn)行網(wǎng)絡(luò)編程中,我們并不需要了解什么同步、異步、阻塞和非阻塞的原理和工作機(jī)制,因為在.Net FrameWrok SDK中已經(jīng)已經(jīng)把這些機(jī)制給封裝好了。3.系統(tǒng)總體設(shè)計 3.1 需求分析  軟件針對局域網(wǎng)內(nèi)部用戶,實現(xiàn)用戶間的即時通信。需要分別實現(xiàn)服務(wù)器端和客戶端的軟件設(shè)計。  服務(wù)器端負(fù)責(zé)監(jiān)聽用戶連接請求,負(fù)責(zé)連接數(shù)據(jù)庫存儲用戶信息,負(fù)責(zé)發(fā)送給用戶好友信息,負(fù)責(zé)發(fā)送心跳報文檢

22、查用戶在線狀態(tài)并即時讓用戶更新好友在新信息。  客戶端發(fā)起主動連接,向服務(wù)器請求登錄或者注冊??蛻舳丝梢孕薷年欠Q,可以加已知用戶為好友(類似于MSN的好友添加功能)??蛻舳酥g可以發(fā)起P2P模式的聊天,可以傳送文件。3.2 系統(tǒng)基本架構(gòu)  基于C/S架構(gòu)的即時通信軟件便于對用戶信息進(jìn)行統(tǒng)一管理和保存,面向特定的用戶,對信息的安全控制能力很強(qiáng)。為了減輕服務(wù)器負(fù)擔(dān),客戶端之間的信息傳遞是采用P2P模式的,服務(wù)器只負(fù)責(zé)用戶的注冊,登錄和用戶在線狀態(tài)的檢驗?;窘Y(jié)構(gòu)如圖: 3.3 功能模塊設(shè)計 CLIENT: 1.注冊: (1)可以

23、完成客戶端注冊,客戶端可以通過填寫信息進(jìn)行注冊,信息被發(fā)送到服務(wù)器端。 2.登錄: (1)客戶可以輸入賬號和密碼進(jìn)行登錄,客戶端會發(fā)送登錄信息等待服務(wù)器響應(yīng),登錄成功后會發(fā)出登錄成功信息并刷新好友列表。 3.修改:(1)密碼修改:應(yīng)該有密碼修改功能 (2)信息修改:可以更改一些注冊信息4.通信:  (1)即時聊天模塊:客戶端與客戶端之間建立線程進(jìn)行即時聊天,也包含有簡單的對稱加解密算法功能。  (2)好友列表:可以對好友列表進(jìn)行添加刪除等動作。 5.文件傳輸:  (1)文件傳輸:文件傳輸功能 SERVER:

24、0;1. 注冊回應(yīng): 對客戶端傳送的注冊信息進(jìn)行判斷。  (1)HASH加密:對用戶的賬號和密碼信息進(jìn)行HASH加密  (2)重復(fù)用戶檢查:將加密后信息與已存在賬號進(jìn)行比較,檢查是否賬號已存在,如果存在就返回錯誤信息(3)注冊成功:將可成功注冊的用戶賬號和密碼寫入數(shù)據(jù)庫內(nèi),并向客戶端返回成功信息 2.修改回應(yīng): (1)對密碼和信息修改請求進(jìn)行判斷,執(zhí)行和返回修改成功信息。 3.登錄回應(yīng): (1)對登錄的賬號和密碼進(jìn)行加密檢查后發(fā)回正確或錯誤情況,并記錄上線信息 。(2)好友列表發(fā)送:給成功登錄的賬號發(fā)送好友列表及好友上線信息

25、。 (3)上線信息發(fā)送:給成功登錄的賬號的好友發(fā)送在線信息(包括IP,端口等等信息)。4.在線情況: (1)對登錄,在線,離線的用戶情況進(jìn)行統(tǒng)計,記錄和通知 (2)心跳測試:每隔一段時間發(fā)送報文測試用戶是否因意外原因離線 (3)情況記錄:將用戶登錄時間,IP,下線時間等信息記錄入數(shù)據(jù)庫3.4 邏輯圖:3.5 數(shù)據(jù)庫設(shè)計 3.5.1 實體關(guān)系圖 服務(wù)器是作為記錄和讀取數(shù)據(jù)庫信息的載體,與客戶端關(guān)系并不復(fù)雜,這里需要重點考慮客戶端之間的關(guān)系。用戶與用戶之間的關(guān)系是較為特殊的遞歸關(guān)系,即描述發(fā)生在兩個相同實體上

26、的關(guān)系。4 系統(tǒng)實現(xiàn) 4.1 使用XML定義的即時通信協(xié)議 4.1.1 信息結(jié)構(gòu)MESSAGE.CS&UMESSAGE.CS 這兩個C#類定義了包括服務(wù)器信息,狀態(tài)信息,注冊信息,登錄信息,聊天信息或者請求文件傳輸信息的函數(shù),服務(wù)器和客戶端通過將它們實例化和序列化再轉(zhuǎn)換成流在網(wǎng)絡(luò)上進(jìn)行傳輸。UMESSAGE.CS主要代碼如下:     Serializable     public class UMessag

27、e              public UMessage()          private string _nickname;         private string _password; 

28、60;       private string _accounts;         private string _email;private int _info;/表示注冊或者登錄信息,客戶端信息0為注冊,1為登錄;服務(wù)器返回信息0為用戶已存在,1為注冊成功,2為服務(wù)器未知錯誤,3為CLIENT在線檢查,10為登錄失敗,11為登錄成功private Friend

29、 _friend;         private int _fn;         private string _fg;        public string Nickname       &

30、#160;              get  return _nickname;               set  _nickname = value;       

31、0;           public string Password                      get  return _password;     &

32、#160;         set  _password = value;           public string Accounts                 

33、60;    get  return _accounts;               set  _accounts = value;                  

34、 public string Email                      get  return _email;               set  

35、;_email = value;                   public int Info             get  return _info; set  _in

36、fo = value;                   public Friend Fri                      get

37、60; return _friend;               set  _friend = value;                   public int Fn &#

38、160;                    get  return _fn;               set  _fn = value;    

39、;               public string Fg                      get  return _fg;   &#

40、160;           set  _fg = value;             由于MESSAGE.CS與UMESSAGE.CS類似,在此不再詳述。 服務(wù)器和客戶端都可以通過相同的代碼對UMESSAGE賦值,再通過XmlSerializer方法進(jìn)行將UMESSAGE序列化為XML文檔,最后將XML文檔轉(zhuǎn)化為網(wǎng)絡(luò)流進(jìn)行傳輸。代碼如

41、下:#region 將登錄信息轉(zhuǎn)為UMessage    private void Traslator()     _message.Accounts=this.TextBox1.Text;     _message.Nickname=""    _message.Password=this.TextBox2.Text;     _message.Email

42、=""     _message.Info=1;     _message.Fri=null;     #endregion4.1.2 數(shù)據(jù)結(jié)構(gòu)FriendStruct 服務(wù)器如果保存和傳遞用戶的好友信息是難點之一。數(shù)據(jù)庫的設(shè)計和信息的傳遞辨別都是比較難實現(xiàn)的。 在數(shù)據(jù)庫方面,每個用戶擁有各自的好友分組信息(UserFav),分組中間使用“,”分隔,在TCP_FriendInfo表中則分別保存了用戶ID和好友ID,使用一個IN

43、T字段保存分組信息。數(shù)據(jù)庫以用戶ID為標(biāo)準(zhǔn)對好友ID和分組信息進(jìn)行內(nèi)連接查詢,就可以得到基本的好友信息了。代碼如下: select * from TCP_UserInfo join TCP_FriendInfo on TCP_FriendInfo.UserID='" + uid + "' and TCP_UserInfo.UserID=TCP_FriendInfo.FriendID 在好友信息的傳輸方面,首先定

44、義一個FriendStruct數(shù)據(jù)結(jié)構(gòu)(當(dāng)然也可以用枚舉完成)如下:using System; using System.Collections.Generic;  using System.Text; namespace TCP      public class FriendStruct             &

45、#160; public struct FileInfo              public int filere;/接收和拒絕信息,1為接收,2為拒絕,3為取消             public string filename;   

46、60;          public long filelength;           public struct Friend              public string accou

47、nt;          public string nickname;          public string IP;         public string status;       

48、  public string fg;/好友分組     在MESSAGE.CS或者UMESSAGE.CS中,我們則定義了FriendStruct的數(shù)組。在C#中使用DATAREADER語句可以逐句讀取數(shù)據(jù)庫查詢的結(jié)果,再依次將結(jié)果賦值FriendStruct數(shù)組元素,就得到了便于發(fā)送和讀取的存放好友信息的數(shù)組。賦值代碼如下:while (getf.Read() /getf即是以上的數(shù)據(jù)庫查詢的datareader語句     

49、0;                ffi.account=getf"UserAccount".ToString();              ffi.IP = getf"UserIP".ToString();    

50、         ffi.nickname = getf"UserNickname".ToString();              ffi.status = getf"UserOnline".ToString();       

51、;       ffi.fg = getf"FriendGroup".ToString();              i+;         getf.Close(); 4.2 數(shù)據(jù)庫連接類 實現(xiàn)一個快捷簡單的數(shù)據(jù)庫連接的相關(guān)代碼是非常有必要的。實

52、現(xiàn)的途徑也多種多樣,鑒于安全性和復(fù)雜性的需求不同,實現(xiàn)方法有簡有繁。本設(shè)計使用了一個簡單的類(UserData.CS)實現(xiàn)了簡單快捷的數(shù)據(jù)庫連接和讀取。主要代碼如下:public static SqlConnection connStr = new SqlConnection("Server=D96B85DD938A465.;uid=sa;pwd=change;database=TCPDB");         public&

53、#160;static SqlDataReader SqlReader(string sql, SqlConnection connstr)           SqlDataReader sqldr = null;             SqlCommand cmd 

54、;= new SqlCommand(sql, connstr);             if (cmd.Connection.State.ToString() = "Closed") cmd.Connection.Open();             &#

55、160;try                              sqldr = cmd.ExecuteReader();            

56、60;             catch (Exception e)               catch (Exception e)            

57、0;              if (e != null) sqldr = null;                          

58、return sqldr;          /數(shù)據(jù)庫操作連接         public static string SqlCmd(string sql, SqlConnection connstr)           &#

59、160;          string errorstr = null;             SqlCommand sqlcmd = new SqlCommand(sql, connstr);       

60、0;      if (sqlcmd.Connection.State.ToString() = "Open") sqlcmd.Connection.Close();             sqlcmd.Connection.Open();          

61、;    try                               sqlcmd.ExecuteNonQuery();             

62、60;             catch (Exception e)                                if 

63、(e != null) errorstr = e.ToString(); sqlcmd.Connection.Close();              return errorstr;         在UserData.CS的基礎(chǔ)上,主程序可以更方便地實現(xiàn)數(shù)據(jù)庫連接操作,對數(shù)據(jù)庫進(jìn)行讀寫和更新,在此不再詳述。 4.

64、3 服務(wù)器端 服務(wù)器端的界面設(shè)計是基于便于測試的目的而實現(xiàn)的。如下圖: 4.3.1 同步套接字網(wǎng)絡(luò)監(jiān)聽 基于同步套接字的網(wǎng)絡(luò)監(jiān)聽器對服務(wù)器來說并不是最好的解決方案,但是仍然可行并且實現(xiàn)簡單。主要代碼如下: 開啟監(jiān)聽端口:         public void Serve()             

65、0;        int port = 8888;             ServerIPEP = new IPEndPoint(IPAddress.Any, port);            

66、 s = new Socket(ServerIPEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);             s.Bind(EndPoint)ServerIPEP);              s.List

67、en(10);             alSock = new ArrayList();以下代碼讀取連入的連接,依次將連接加入可變長數(shù)組alsock,并且讀取傳入的信息,進(jìn)行反串行化:while (true)                  &#

68、160;           try                                      

69、;uc = s.Accept();                      alSock.Add(uc);                     this.

70、tb_states.AppendText(System.Convert.ToString(uc);                      byte data = new byte2048;             &

71、#160;        int rect = uc.Receive(data);                      byte chat = new byterect;      &

72、#160;              Buffer.BlockCopy(data, 0, chat, 0, rect);                     UMessage umessage&#

73、160;= (UMessage)_translator.Deserialize(new MemoryStream(chat);                     int info = umessage.Info; 對反串行化后的信息進(jìn)行處理,通過info參數(shù)辨認(rèn)客戶端行為(注冊或者登錄),對注冊的信息進(jìn)行數(shù)據(jù)庫查詢,注冊信息可插入,

74、則將用戶信息插入數(shù)據(jù)庫,否則返回客戶端“注冊出錯”的信息: #region 處理用戶注冊信息                     if (info=0)/分辨出用戶發(fā)送的是注冊信息               

75、60;                              string Accounts = umessage.Accounts;           

76、              SqlDataReader usdr = FPara.SqlReader("select * from TCP_UserInfo where UserAccount='" + Accounts + "'", FPara.connStr);

77、0;                         if (usdr != null)                    &

78、#160;                                  if (usdr.Read()            

79、0;                                                  #re

80、gion 此處寫入返回注冊失敗的代碼          Socket sc = (Socket)alSockalSock.IndexOf(uc, 0);                         

81、0;        sc.Send(chat);                                  #endregion     &#

82、160;                                                   

83、   else                                #region 此處寫入插入數(shù)據(jù)庫用戶注冊信息的代碼 Stream ms = new MemoryStream();  &

84、#160;                              Socket sc = (Socket)alSockalSock.IndexOf(uc, 0);        

85、;                         if (FPara.SqlCmd("insert into TCP_UserInfo (UserAccount,UserNickname,UserEmail,JoinDate,UserIP,UserPassword) values(

86、9;" + umessage.Accounts + "','" + umessage.Nickname + "','" + umessage.Email + "','" + System.DateTime.Now.ToString() + "','" + (IPEn

87、dPoint)uc.RemoteEndPoint).Address.ToString() + "','" + umessage.Password + "')", FPara.connStr) = null)                    

88、                                                  

89、umessage.Info = 1;                                     _translator.Serialize(ms, umessage); byte

90、0;d = new bytems.Length;                                      ms.Seek(0, SeekOrigin.Begin);

91、0;                                     ms.Read(d, 0, d.Length);        

92、;                              sc.Send(d);                   

93、;                                                else &

94、#160;                                                 &

95、#160;                 umessage.Info = 2;                           

96、60;         _translator.Serialize(ms, umessage);                                 

97、0;    byte d = new bytems.Length;                                      ms.Seek(0

98、, SeekOrigin.Begin);                                      ms.Read(d, 0, d.Length); sc.Send(d); 

99、                                                   

100、;               #endregion                                   

101、;                     usdr.Close();                            &#

102、160;                          #endregion  如果發(fā)現(xiàn)用戶發(fā)送的是登錄信息,就根據(jù)登錄信息中的用戶名和密碼判斷是否存在用戶,密碼是否正確,成功后再查詢出用戶的好友信息并且賦值給FriendStruct,再將信息返回給客戶端:       &#

103、160;             #region 處理用戶登錄信息                     else if (info = 1)/分辨出用戶發(fā)送的是登錄信息    

104、              string Accounts = umessage.Accounts;                         string Password =

105、60;umessage.Password;                       SqlDataReader usdr = FPara.SqlReader("select * from TCP_UserInfo where UserAccount='" +

106、 Accounts + "' and UserPassword='"+Password+"'", FPara.connStr);                         if (usdr !=

107、60;null)                                                 

108、60;     if (usdr.Read()                                string uid=usdr"UserID".ToString();  

109、60;                          umessage.Fg = usdr"UserFav".ToString();             

110、0;                    usdr.Close();                            Sq

111、lDataAdapter sdr = new SqlDataAdapter("select * from TCP_UserInfo join TCP_FriendInfo on TCP_FriendInfo.UserID='" + uid + "' and TCP_UserInfo.UserID=TCP_FriendInfo.FriendID", FPara.c

112、onnStr);                                  DataSet ds = new DataSet();       

113、0;                          sdr.Fill(ds, "find");                  

114、60;          int xxx=ds.Tables"find".Rows.Count;                            FPara.SqlCmd("updat

115、e TCP_UserInfo set UserIP='" + (IPEndPoint)uc.RemoteEndPoint).Address.ToString() + "' , UserOnline=1 where UserAccount='" + Accounts + "'", FPara.connStr);    

116、                              ff=new Friendxxx;                 &

117、#160;                int i=0;                            SqlDataReader getf

118、 = FPara.SqlReader("select * from TCP_UserInfo join TCP_FriendInfo on TCP_FriendInfo.UserID='" + uid + "' and TCP_UserInfo.UserID=TCP_FriendInfo.FriendID", FPara.connStr);   

119、60;                              while (getf.Read()                

120、60;                   ffi.account=getf"UserAccount".ToString();                       

121、0;              ffi.IP = getf"UserIP".ToString();                           

122、0;          ffi.nickname = getf"UserNickname".ToString(); ffi.status = getf"UserOnline".ToString();                   &#

123、160;                  ffi.fg = getf"FriendGroup".ToString();                      

124、60;               i+;                                   

125、;                             getf.Close();                  

126、0;                #region 此處寫入登錄成功代碼                  Stream ms = new MemoryStream();     

127、                          Socket sc = (Socket)alSockalSock.IndexOf(uc, 0);            

128、0;                     this.lb_users.Items.Add(alSock.IndexOf(uc).ToString();                    

129、60;             umessage.Info = 11;                                 &#

130、160;umessage.Fri = ff;                                  umessage.Fn = xxx;       

131、;                      _translator.Serialize(ms, umessage);                     

132、             byte d = new bytems.Length;                                  ms.Seek(0,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論