余長江, 周淵平, 呂海龍
(四川大學 電子信息學院,四川 成都 610065)
Linux作為一種開放源代碼的操作系統(tǒng),對于軟件未來的發(fā)展方向起著一定的引導作用,其主要特點有:源代碼完全開放;具有多用戶特性并支持多進程與多線程;系統(tǒng)安全性可靠;擁有良好的用戶界面;網(wǎng)絡功能強大;支持多平臺;良好的兼容性等等。由于 Linux系統(tǒng)的諸多特性,使其在服務器和個人應用以及企業(yè)開發(fā)領域中的應用越來越普遍[1],在Linux環(huán)境下開發(fā)圖形界面也成為了眾多編程者的選擇。
GIMP是一種基于 Linux平臺且能與Photoshop相媲美的圖像處理軟件,而 GTK+最初則是 GIMP的專用開發(fā)庫,后來逐漸發(fā)展為Linux下開發(fā)圖形界面應用程序的主流工具之一,它使用 C語言開發(fā),可以靈活的應用于不同系統(tǒng),備受開源軟件開發(fā)者矚目。GTK+具有的特性如下:動態(tài)類型系統(tǒng);用C語言編寫對象系統(tǒng);實現(xiàn)了繼承、類型檢驗,以及信號/回調(diào)函數(shù)的基礎結(jié)構(gòu);類型和對象系統(tǒng)不特別針對GUI;GTK Widget對象使用對象系統(tǒng),它定義了GTK+的圖形組件的使用接口;大量的 GTKWidget構(gòu)件[2]。GTK+2.0的協(xié)議 GNU寬通用公共許可證(LGPL,GNU Lesser General Public License),允許任何開發(fā)者使用(包括那些開發(fā)中的專利軟件)且不收取任何費用。GTK+2.0是當今唯一100%零付費的工業(yè)級的圖形界面開發(fā)工具 。采用GTK+2.0編程技術(shù)設計出一個聊天室,再結(jié)合多線程技術(shù),可實現(xiàn)在服務器端和客戶端之間的聊天功能。
本聊天室分為服務器端和客戶端兩部分,采用GTK+2.0,即可用簡短的代碼來編寫窗口并向窗口中插入各個控件,通過靈活地使用信號/回調(diào)函數(shù)機制,實現(xiàn)通信連接、信息發(fā)送、關閉窗口等功能,聊天室如圖1和圖2所示。首先運行服務器端,單擊“開啟”按鈕后服務器端等待客戶端連接,再運行客戶端,在登陸框輸入服務器端IP,單擊“登錄”按鈕即可與服務器端連接,然后雙方就可以進行通信了。
圖1 服務器端聊天室
圖2 客戶端聊天室
聊天過程采用TCP/IP協(xié)議下的Client/Server網(wǎng)絡通信模式實現(xiàn),通過套接字(Socket)接口可方便的實現(xiàn)TCP、UDP傳輸協(xié)議完成數(shù)據(jù)的網(wǎng)絡傳輸[4],對可靠性要求高的數(shù)據(jù)通訊系統(tǒng)往往使用TCP協(xié)議傳輸數(shù)據(jù) 。Socket是網(wǎng)絡通信的基本構(gòu)件,可看作網(wǎng)絡通信的一個端點,在網(wǎng)絡通信中使用 Socket函數(shù)必須有客戶和服務器2個進程,以實現(xiàn)網(wǎng)絡端點之間的連接和數(shù)據(jù)交換[6]。在雙方進行通信前,要先運行服務器端程序,等待客戶端的連接。開啟服務器端后主要有以下工作。
(1)建立一個socket通信
調(diào)用函數(shù)socket(int domain, int type, int protocol)來建立一個套接字,即向系統(tǒng)注冊,通知系統(tǒng)建立一個通信端口。參數(shù) domain 表示所采用的地址類型,此處取值為AF_INET,即ARPA internet地址格式;type為新套接口的類型描述,取值為SOCK_STREAM,表示提供雙向連續(xù)且可信賴的數(shù)據(jù)流,即 TCP;protocol表示 socket所使用傳輸協(xié)議的編號,通常取值為0。若成功則返回一個socket描述符。
(2)對 socket定位
調(diào)用函數(shù) bind(int sockfd, struct sockaddr *my_addr, int addrlen)將新建的套接字與本地網(wǎng)絡地址聯(lián)系起來。sockfd即為調(diào)用socket函數(shù)后所返回的socket描述符;my_addr為包含本機IP地址和端口號的指針;addrlen為sockaddr的結(jié)構(gòu)長度。
(3)等待客戶端的連接
調(diào)用函數(shù)listen(int sockfd, int backlog)使socket處于監(jiān)聽模式。參數(shù)backlog表示同時能處理的最大連接數(shù)目。listen()并未開始接收連線,只是設置socket為監(jiān)聽模式,調(diào)用accept()成功后才是真正接收客戶端的連線。所以listen()應該在socket(),bind()之后,在accept()之前調(diào)用。
(4)接收客戶端socket連線
調(diào)用函數(shù)accept(int sockfd, struct sockaddr *addr,int *addrlen)來接收客戶端的連線請求。sockfd是被監(jiān)聽的socket的描述符;連線成功后,addr所指的結(jié)構(gòu)會被填入客戶端主機的地址數(shù)據(jù);addrlen是sockaddr的結(jié)構(gòu)長度。若連接成功則返回新的socket處理代碼。
相對服務器端復雜的過程而言,客戶端的工作比較簡單。
運行客戶端程序后,在登錄框輸入服務器端IP地址,該點間隔地址將被函數(shù) inet_addr()轉(zhuǎn)換成in_addr結(jié)構(gòu)的地址,然后單擊“登陸”按鈕,此時程序首先調(diào)用函數(shù)socket(),像服務器端那樣建立一個套接字,然后調(diào)用函數(shù) connect(int sockfd, struct sockaddr *serv_addr, int addrlen)將客戶端連接至服務器端。sockfd即為新建的客戶端的socket描述符;serv_addr所指向的結(jié)構(gòu)被填入經(jīng) inet_addr()轉(zhuǎn)換后的地址;參數(shù)addrlen為sockaddr的結(jié)構(gòu)長度。
客戶端與服務器端連接成功后,雙方即可進行通信,send()和recv()這兩個函數(shù)用來在面向連接的socket上進行數(shù)據(jù)傳輸,其調(diào)用方式如下:
1)函數(shù)send(int sockfd, const void *msg, int len,int flags)用來發(fā)送數(shù)據(jù)。sockfd是建立好連接的socket描述符;msg指針指向要發(fā)送的數(shù)據(jù);len是以字節(jié)為單位的數(shù)據(jù)的長度,flags設置為0。
2)函 數(shù) recv(int sockfd, void *buf, int len,unsigned int flags)用來接收數(shù)據(jù)。sockfd是建立好連接的socket描述符;buf指向存放接收數(shù)據(jù)的緩沖區(qū);len是緩沖的長度;flags設置為0。
進入聊天程序后,程序要不斷檢測是否有新的信息發(fā)送過來,如果只是簡單的采用無限循環(huán)這個操作,程序會進入死機狀態(tài),此時就無法進行發(fā)送信息等其他的操作了,而使用多線程技術(shù),就可將接收信息的操作置于一個新的線程,從而避免無法發(fā)送信息的情況。所謂多線程,就是將一個進程分成多個執(zhí)行線程,各個線程可以獨立運行。多線程程序采用一種多任務、并發(fā)的工作方式,主要優(yōu)點有:提高應用程序的響應;更有效的使用多處理器;改善程序結(jié)構(gòu);占用較少的系統(tǒng)資源。
在 main函數(shù)中創(chuàng)建多個線程,則該程序運行時,操作系統(tǒng)為每個線程分配不同的CPU時間片,并根據(jù)線程優(yōu)先級進行調(diào)度。由于每個時間片的時間很短,雖然實際上同一時刻只有一個線程在運行,但是看上去好像多個線程是并發(fā)運行[7]??蛻舳顺绦蛑械亩嗑€程代碼框架如下:
若使用線程,在初始化 GTK+庫函數(shù)之前必須運行 g_thread_init(NULL)和 gdk_threads_init()來初始化線程應用。創(chuàng)建線程調(diào)用函數(shù)g_thread_create(),如上面程序中,g_thread_create()函數(shù)用來生成接收消息的線程,get_message()即為線程的具體事件回調(diào)函數(shù)。當線程例程(即線程執(zhí)行的代碼)開始時,通過gdk_threads_enter()來獲得一個唯一的全局鎖,當線程例程返回時,通過gdk_threads_leave()釋放該全局鎖。線程創(chuàng)建成功后,新創(chuàng)建的線程開始運行回調(diào)函數(shù)且不影響原來的線程繼續(xù)運行。同樣,服務器端的多線程編程與此類似。
隨著開源編程的迅猛發(fā)展,在Linux下開發(fā)程序已成為一種潮流,XWindow和 GNU編譯系統(tǒng)已成為Linux上最主要的軟件系統(tǒng),GTK+作為這兩者相結(jié)合的編程開發(fā)包更是廣受歡迎。通過對GTK+編程技術(shù)的研究,設計了一個簡單的聊天室,采用TCP/IP協(xié)議下的Client/Server網(wǎng)絡通信模式,詳細介紹了聊天時雙方通信的建立和信息收發(fā)的方法,再結(jié)合多線程技術(shù),實現(xiàn)了雙方正常的聊天功能。
[1]初振林.Linux安全強化方案[J].信息安全與通信保密,2007(11):49-50.
[2]張同光,潘紅.Linux中GTK+編程技術(shù)研究及其應用[J].軟件導刊, 2007(08):38-40.
[3]宋國偉.GTK+2.0編程范例[M].北京:清華大學出版社,2002.
[4]陳周國.基于Linux QT技術(shù)的遠程監(jiān)控GUI設計[J].通信技術(shù), 2009, 42(12):234-236.
[5]李磊,劉嘉勇.關于對 QQ文件傳輸特點的研究[J].信息安全與通信保密, 2011(04):36-37.
[6]曹玲芝.基于DDE和Socket技術(shù)的網(wǎng)絡控制系統(tǒng)仿真平臺[J].通信技術(shù), 2009,42(08):30-33.
[7]金衛(wèi)民,魯志康.GTK環(huán)境下的多線程設計[J].微計算機信息, 2008, 24(07):310-312.