【正文】
sizeof(struct in_addr)]。 * 套接字地址 結(jié)構(gòu) struct sockaddr 定義了一種通用的套接字地址,其定義如下: struct sockaddr { unsigned short sa_family。 if (sock_fd0) { perror(socket creating error)。 然后雙方可以通過(guò)操作各自的描述符來(lái)進(jìn)行傳輸數(shù)據(jù)。然后通過(guò) bind 函數(shù)將這個(gè) socket 綁定到一個(gè) Client 知道的端口上,接著 server 調(diào)用 accept 函數(shù)設(shè)置傾聽(tīng)隊(duì)列的長(zhǎng)度,為接收來(lái)自 Client端的請(qǐng)求做準(zhǔn)備,而后 Server 調(diào)用 Accept,開(kāi)始在所綁定的端口傾聽(tīng)來(lái)自 Client端的連接請(qǐng)求??蛻?hù)隨機(jī)申請(qǐng)一個(gè)套接字號(hào),服務(wù)器擁有全局公認(rèn)的套接字號(hào),任何客戶(hù)可以向它發(fā)出 連接請(qǐng)求和信息請(qǐng)求。一個(gè)文件描述符只是一個(gè)簡(jiǎn)單的整形數(shù)值,它代表一個(gè)被打開(kāi)的文件(這里的文件指廣義的 UNIX 文件)。什么是套接字?套接字的英文原意是“孔”或“插座”,作為 BSD UNIX 的進(jìn)程通信機(jī)制,取后一種意義。之后隨著不斷的完善,和 GNU 軟件的支持, LINUX 已經(jīng)是一個(gè)功能強(qiáng)大的類(lèi) UNIX 操作系統(tǒng)了。 LINUX 是什么?按照 LINUX 開(kāi)發(fā)者的說(shuō)法, LINUX 是一個(gè)遵循 POSIX 標(biāo)準(zhǔn)的免費(fèi)操作系統(tǒng)。Linux 網(wǎng)絡(luò)編程 —— 實(shí)現(xiàn)一個(gè)局域網(wǎng)的電子郵件系統(tǒng) 摘要 計(jì)算機(jī)網(wǎng)絡(luò)的迅速發(fā)展,對(duì)人類(lèi)社會(huì)諸多領(lǐng)域產(chǎn)生了巨大的影響。 關(guān)鍵字 : Linux, 網(wǎng)絡(luò)編程,套接字,服務(wù)器,客戶(hù)端,電子郵件系統(tǒng) Abstract The rapid development of the puter works has been making a great influence in many fields of human society. Among a great many works operating systems, Linux is obtaining more and more attention from people by its excellent this graduate design, our task is to develop a system based on a lan with Linux as its operating system. This article includes two parts. In part one, we will make an introduction to Linux operating system and the work programming environment in Linux. In particular, the BSD socket functions are analyzed in great detail, for they will be used in later programming work. In part two, we present the implementation of our mail system, from whole designing to detail designing, and the C program source files written by me is attached to the end of this article. Keywords: Linux, work programming , socket, server, client, system Linux 網(wǎng)絡(luò)編程 —— 實(shí)現(xiàn)一個(gè)局域網(wǎng)的電子郵件系統(tǒng) 目錄 第一部分 環(huán)境分析 第一章 LINUX 的發(fā)展歷史及趨勢(shì) …………………………………… .3 第二章 LINUX 網(wǎng)絡(luò)編程環(huán)境分析 第一節(jié) 套接字簡(jiǎn)介 ………………………………………… 4 第二節(jié) socket 編程的基本流程 …………………………… .4 第二節(jié) BSD 套接字函數(shù)介紹 ……………………………… 5 第二部分 郵件系統(tǒng)實(shí)現(xiàn) 第三章 郵件系統(tǒng)介紹 第一節(jié) 概述 ………………… ……………………………… 13 第二節(jié) 模塊劃分 …………………………………………… 14 第三節(jié) 服務(wù)器程序和客戶(hù)端程序的詳細(xì)設(shè)計(jì)與分析 …… 16 設(shè)計(jì)體會(huì)與致謝 ……………………………………………………………… .…29 參考文獻(xiàn) ………………………………………………………………………… .30 附錄 服務(wù)器程序和客戶(hù)端程序的源代碼 ………………………………………………… ..31 Linux 網(wǎng)絡(luò)編程 —— 實(shí)現(xiàn)一個(gè)局域網(wǎng)的電子郵件系統(tǒng) 第一章 LINUX 的發(fā)展歷史及趨勢(shì) 在迅猛發(fā)展的國(guó)際互聯(lián)網(wǎng)上,有這樣一群人,他們是一支由編程高手、業(yè)余計(jì)算機(jī)玩家和黑客們組成的奇怪隊(duì)伍,完全獨(dú)立的開(kāi)發(fā)出在功能上毫不遜色于微軟的全新的免費(fèi) UNIX 操作系統(tǒng) —— Linux,成為網(wǎng)絡(luò)上一支不可輕視的力量,短短幾年時(shí)間就成了微軟的一個(gè)強(qiáng)勁對(duì)手。 1991 年,一位來(lái)自芬蘭赫爾辛基大學(xué)的年輕人 Linus Benedict Torvalds 在實(shí)習(xí) Minix 時(shí)發(fā) 現(xiàn)它功能還很不完善,于是決心自己寫(xiě)一個(gè)保護(hù)模式下的操作系統(tǒng),這就是 Linux 的原型。 Linux 網(wǎng)絡(luò)編程 —— 實(shí)現(xiàn)一個(gè)局域網(wǎng)的電子郵件系統(tǒng) 第二章 LINUX 網(wǎng)絡(luò)編程環(huán)境分析 第一節(jié) 套接字簡(jiǎn)介 網(wǎng)絡(luò)程序設(shè)計(jì)全靠套接字( SOCKET)接收和發(fā)送信息。 在 UNIX 系統(tǒng)中,任何對(duì) I/O 的操作都是通過(guò)讀或?qū)懸粋€(gè)文件描述符來(lái)實(shí)現(xiàn)的。 套接字是面向客戶(hù) — 服務(wù)器模型設(shè)計(jì),針對(duì)客戶(hù)和服務(wù)器提供不同的套接字操作。 Server 端首先調(diào)用 socket 創(chuàng)建一Linux 網(wǎng)絡(luò)編程 —— 實(shí)現(xiàn)一個(gè)局域網(wǎng)的電子郵件系統(tǒng) 個(gè)一定類(lèi)型的 socket。以上過(guò)程體現(xiàn)了 TCP 協(xié)議三次握手建立連接的思想。 以下代碼將創(chuàng)建一個(gè) TCP 的套接字描述符: int sock_fd=socket(AF_INET,SOCK_STREAM,0)。參數(shù) addrlen 指定這個(gè)套接字地址的長(zhǎng)度。 /*端口號(hào) */ struct in_addr sin_addr。 Linux 系統(tǒng)提供了 4 個(gè)庫(kù)函數(shù)來(lái)進(jìn)行字節(jié)順序的轉(zhuǎn)化: includei/ unsigned long int htonl(unsigned long int hostlong)。 int ret,sock_fd。 exit(1)。在 server 進(jìn)程中,由于進(jìn)程通常使用的是一個(gè)熟知端口,所以需要調(diào)用 bind()向系統(tǒng)登記一個(gè)固定端口。 =AF_INET。對(duì)于一臺(tái)只有一個(gè) IP地址的主機(jī),它就對(duì)應(yīng)于它的 IP 地址。函數(shù)的形式如下: includesys/ int accept(int sockfd,struct sockaddr *addr,int *addrlen)。 函數(shù) read()和 write() read()和 write()用于數(shù)據(jù)的接收和發(fā)送。如果 read 出錯(cuò),則返回 1,并設(shè)置 errno。進(jìn)程將不能再使用套接字描述符來(lái)訪(fǎng)問(wèn)套接字,但是 TCP 可能并沒(méi)有刪除套接字結(jié)構(gòu),因?yàn)榭赡茉诎l(fā)送數(shù)據(jù)緩沖區(qū)還有數(shù)據(jù)沒(méi)有發(fā)送完。 int sin_size。(),8)。 connect request......\n)。 close(new_fd)。s ip address server39。 i_aton(argv[1],amp。 printf(Receive from server %s :\n %s,argv[1],buf)。由于是為了實(shí)習(xí)目的模擬現(xiàn)實(shí)的郵件系統(tǒng),該郵件系統(tǒng)較現(xiàn)實(shí)中的郵件系統(tǒng)功能上有較大的簡(jiǎn)化?;窘Y(jié)構(gòu)如下: 服務(wù)器主程序調(diào)用以下兩大模塊: 服務(wù)器文件處理模塊 ⑴信件管理子模塊 (打開(kāi)郵件 列表,打開(kāi)郵件,刪除郵件) ⑵用戶(hù)信息管理子模塊 (保存帳號(hào)密碼對(duì),驗(yàn)證密碼) 服務(wù)器通信模塊 (服務(wù)器向客戶(hù)傳郵件,服務(wù)器向客戶(hù)傳服務(wù)響應(yīng)信息) 客戶(hù)端主程序調(diào)用以下兩大模塊 客戶(hù)端界面提供模塊 客戶(hù)端通信模塊 (客戶(hù)向服務(wù)器傳郵件,客戶(hù)向服務(wù)器傳服務(wù)請(qǐng)求信息) 我們實(shí)現(xiàn)的郵件系統(tǒng)的運(yùn)行大致過(guò)程為:服務(wù)器和客戶(hù)機(jī)分別進(jìn)入主程序,調(diào)用各自通信模塊建立連接。 每個(gè)用戶(hù)擁有一個(gè)郵件列表文件。根據(jù)用戶(hù)名及用戶(hù)傳過(guò)來(lái)的待刪郵件的號(hào)碼利用系統(tǒng)調(diào)用將相應(yīng)郵件刪除。 服務(wù)器端通信模塊 服務(wù)器程序 在啟動(dòng)時(shí)便調(diào)用 SOCKET 函數(shù)族,創(chuàng)建套接字,綁定端口,開(kāi)始等待客戶(hù)端的連接。 ( 3)進(jìn)入 郵箱界面:打印郵件列表,提供“讀郵件”,“發(fā)郵件”,“刪除郵件”,“退出郵箱”,“注銷(xiāo)用戶(hù)”等命令選擇。此模塊與服務(wù)器不同的是需要知道服務(wù)器工作在哪個(gè)端口,這里存在一些技術(shù)問(wèn)題,這個(gè)問(wèn)題將在后面進(jìn)行討論。一個(gè)郵件結(jié)構(gòu)包括以下幾項(xiàng):收信者,Linux 網(wǎng)絡(luò)編程 —— 實(shí)現(xiàn)一個(gè)局域網(wǎng)的電子郵件系統(tǒng) 發(fā)信者,主題,郵件正文,發(fā)信時(shí)間,郵件編號(hào)等等。 用于同步的函數(shù)有以下一對(duì): int SendSockChar(int sockfd,char ch):發(fā)送一個(gè)同步字符。在利用系統(tǒng)函數(shù) read(),write() 的基礎(chǔ)上,還另外使用了幾個(gè)自編的函數(shù): readline(),sockendl(),CutEndl(),分 別說(shuō)明如下: int readline(int,void*,int): 從套接字中讀取一行內(nèi)容。函數(shù)SOCKENDLINE 實(shí)現(xiàn)補(bǔ)發(fā)換行符的功能。 13~16 行定義了一些常量, MAXSIZE 為緩沖區(qū)的最大容量。 客戶(hù)端主程序:客戶(hù)端的 main()函數(shù)比服務(wù)器的更加簡(jiǎn)單。 a、 服務(wù)器主函數(shù) int ServerMain(int sockfd): 當(dāng)一個(gè)用戶(hù)與服務(wù)器建立連接,服務(wù)器程序產(chǎn)生一個(gè)子進(jìn)程為之服務(wù),該子Linux 網(wǎng)絡(luò)編程 —— 實(shí)現(xiàn)一個(gè)局域網(wǎng)的電子郵件系統(tǒng) 進(jìn)程調(diào)用 ServerMain 函數(shù)為客戶(hù)服務(wù),此函數(shù)返回,服務(wù)即結(jié)束。這些函數(shù)在服務(wù)器和客戶(hù)端成對(duì)出現(xiàn),從而能實(shí)現(xiàn)成功的通信功能。 /*刪除郵件功能服務(wù)器端函數(shù),299~313 行 */ int SendMailSev(int sockfd,char*Usr)。 /* 發(fā)郵件功能客戶(hù)端函數(shù), 714~758 行 */ 流程圖 以下是服務(wù)器程序和客戶(hù)端程序的流程圖,從圖中可以看到本地各函數(shù)的調(diào)用關(guān)系,和兩端對(duì)應(yīng)函數(shù)的對(duì)應(yīng)關(guān)系。 驗(yàn)證密碼。 int StoreMail(MailStruct * Mail)。當(dāng)服務(wù)器收到欲讀郵件的客戶(hù)發(fā)過(guò)來(lái)的郵件代號(hào),根據(jù)該代號(hào)在相應(yīng)文件中查找到欲讀的郵件,把內(nèi)容寫(xiě)到一個(gè)緩沖里,用 BUF 返回。 以上六個(gè)函數(shù)由合作者唐志軍實(shí)現(xiàn),限于篇幅,不列出具體實(shí)現(xiàn)的源代碼。 LINUX 截圖程序得到。 tangzj 選擇發(fā)郵件命令,給 ducktang 編輯了一封郵件并發(fā)出。也就是附件的文件類(lèi)型應(yīng)該用文本形式另外發(fā)送,這樣才能讓接受者知道福附件到底是什么文件。 (4)服務(wù)器端口號(hào)問(wèn)題:在上一節(jié)介紹 客戶(hù)端通信模塊時(shí)提到一個(gè)問(wèn)題,即客戶(hù)程序必須知道服務(wù)器程序的 IP 地址和端口號(hào), IP 地址是固定的,但端口號(hào)卻不一定固定。在這一過(guò)程中,實(shí)現(xiàn)老師給出這一任務(wù)的初衷,不要求做出來(lái)的東西有多完美,只要求在動(dòng)手的過(guò)程中能學(xué)到書(shū)本上學(xué)不到的東西。 鍛煉了團(tuán)隊(duì)合作能力。 21 char from[MAXSIZE]。 31 int readline(int,void*,int)。 Linux 網(wǎng)絡(luò)編程 —— 實(shí)現(xiàn)一個(gè)局域網(wǎng)的電子郵件系統(tǒng) 41 42 int ReadMailSev(int sockfd)。 57 new_fd=accept(sockfd,(struct sockaddr*)amp。 66 } 67 close(new_fd