




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、Linux下的Socket編程實(shí)現(xiàn)一對一通信 田昕煜 (1.通信工程,13081405)摘要: 以當(dāng)下社會(huì)普遍應(yīng)用QQ,微信,微博等聊天工具為引,設(shè)計(jì)了簡單的Linux系統(tǒng)下的socket編程實(shí)現(xiàn)客戶端與服務(wù)器的一對一通信。關(guān)鍵詞: 多線程,socket創(chuàng)建,bind函數(shù),connect函數(shù),listen函數(shù),accept函數(shù),數(shù)據(jù)傳輸0 基本原理本聊天室程序在 Ubuntu 下,采用 C 語言實(shí)現(xiàn),結(jié)構(gòu)為 Client/Server 結(jié)構(gòu);服務(wù)端程序通過共享存儲(chǔ)區(qū)存儲(chǔ)聊天數(shù)據(jù),并發(fā)送給每個(gè)連接的客戶端;服務(wù)端程序和客戶端程序都是通過父子進(jìn)程分別負(fù)責(zé)發(fā)送和接收數(shù)據(jù)的,以避免數(shù)據(jù)沖撞;1設(shè)計(jì)思路
2、及功能1.1 總體設(shè)計(jì)框架1.2程序設(shè)計(jì)方案Socket創(chuàng)建 socket函數(shù)原型為: #include #include int socket(int domain, int type, int protocol); 功能:調(diào)用成功,返回socket文件描述符;失敗,返回1,并設(shè)置errno 參數(shù)說明: domain指明所使用的協(xié)議族,通常為PF_INET,表示互聯(lián)網(wǎng)協(xié)議族(TCP/IP協(xié)議 族; type參數(shù)指定socket的類型: SOCK_STREAM 提供有序、可靠、雙向及基于連接的字節(jié)流 SOCK_DGRAM 支持?jǐn)?shù)據(jù)報(bào) SOCK_SEQPACKET 提供有序、可靠、雙向及基于連接
3、的數(shù)據(jù)報(bào)通信 SOCK_RAW 提供對原始網(wǎng)絡(luò)協(xié)議的訪問 SOCK_RDM 提供可靠的數(shù)據(jù)報(bào)層,但是不保證有序性 protocol通常賦值0. socket描述符是一個(gè)指向內(nèi)部數(shù)據(jù)結(jié)構(gòu)的指針,它指向描述符表入口。調(diào)用socket函數(shù)時(shí),socket執(zhí)行體將建立一個(gè)socket,實(shí)際上建立一個(gè)socket意味著為一個(gè)socket數(shù)據(jù)結(jié)構(gòu)分配存儲(chǔ)空間。socket執(zhí)行體為你管理描述符表。 兩個(gè)網(wǎng)絡(luò)程序之間的一個(gè)網(wǎng)絡(luò)連接包括五種信息:通信協(xié)議、本地協(xié)議地址、本地主機(jī)端口、遠(yuǎn)端主機(jī)地址和遠(yuǎn)端協(xié)議端口。socket數(shù)據(jù)結(jié)構(gòu)中包含這五種信息。Socket綁定 bind函數(shù)原型為: #include #in
4、clude int bind(int sock_fd,struct sockaddr *my_addr, int addrlen); 功能說明:將套接字和指定的端口相連。成功返回0,否則,返回1,并置errno. 參數(shù)說明:sock_fd是調(diào)用socket函數(shù)返回的socket描述符, my_addr是一個(gè)指向包含有本機(jī)IP地址及端口號等信息的sockaddr類型的指針; addrlen常被設(shè)置為sizeof(struct sockaddr)。 struct sockaddr結(jié)構(gòu)類型是用來保存socket信息的: struct sockaddr unsigned short sa_family
5、; /* 地址族, AF_xxx */ char sa_data14; /* 14 字節(jié)的協(xié)議地址 */ ; sa_family一般為AF_INET,代表Internet(TCP/IP)地址族; sa_data則包含該socket的IP地址和端口號。 另外還有一種結(jié)構(gòu)類型: struct sockaddr_in short int sin_family; /* 地址族 */ unsigned short int sin_port; /* 端口號 */ struct in_addr sin_addr; /* IP地址 */ unsigned char sin_zero8; /* 填充0 以保持與
6、struct sockaddr同樣大小 */ ; 這個(gè)結(jié)構(gòu)更方便使用。sin_zero用來將sockaddr_in結(jié)構(gòu)填充到與struct sockaddr同樣的長度,可以用bzero()或memset()函數(shù)將其置為零。指向sockaddr_in 的指針和指向sockaddr的指針可以相互轉(zhuǎn)換,這意味著如果一個(gè)函數(shù)所需參數(shù)類型是sockaddr時(shí),你可以在函數(shù)調(diào)用的時(shí)候?qū)⒁粋€(gè)指向 sockaddr_in的指針轉(zhuǎn)換為指向sockaddr的指針;或者相反。 使用bind函數(shù)時(shí),可以用下面的賦值實(shí)現(xiàn)自動(dòng)獲得本機(jī)IP地址和隨機(jī)獲取一個(gè)沒有被占用的端口號: my_addr.sin_port = 0;
7、/* 系統(tǒng)隨機(jī)選擇一個(gè)未被使用的端口號 */ my_addr.sin_addr.s_addr = INADDR_ANY; /* 填入本機(jī)IP地址 */ 通過將my_addr.sin_port置為0,函數(shù)會(huì)自動(dòng)為你選擇一個(gè)未占用的端口來使用。同樣,通過將my_addr.sin_addr.s_addr置為INADDR_ANY,系統(tǒng)會(huì)自動(dòng)填入本機(jī)IP地址。 注意在使用bind函數(shù)是需要將sin_port和sin_addr轉(zhuǎn)換成為網(wǎng)絡(luò)字節(jié)優(yōu)先順序。 計(jì)算機(jī)數(shù)據(jù)存儲(chǔ)有兩種字節(jié)優(yōu)先順序:高位字節(jié)優(yōu)先和低位字節(jié)優(yōu)先(大端和小端)。Internet上數(shù)據(jù)以高位字節(jié)優(yōu)先順序在網(wǎng)絡(luò)上傳輸,所以對于在內(nèi)部是以低位字
8、節(jié)優(yōu)先方式存儲(chǔ)數(shù)據(jù)的機(jī)器,在Internet上傳輸數(shù)據(jù)時(shí)就需要進(jìn)行轉(zhuǎn)換,否則就會(huì)出現(xiàn)數(shù)據(jù)不一致。 Bind()函數(shù)在成功被調(diào)用時(shí)返回0;出現(xiàn)錯(cuò)誤時(shí)返回-1并將errno置為相應(yīng)的錯(cuò)誤號。 需要注意的是,在調(diào)用bind函數(shù)時(shí)一般不要將端口號置為小于1024的值,因?yàn)?到1024是保留端口號,你可以選擇大于1024中的任何一個(gè)沒有被占用的端口號。連接 面向連接的客戶程序使用connect函數(shù)來配置socket并與遠(yuǎn)端服務(wù)器建立一個(gè)TCP連接,其函數(shù)原型為: #include #include int connect(int sock_fd, struct sockaddr *serv_addr,i
9、nt addrlen); 功能說明:客戶端發(fā)送服務(wù)請求。成功返回0,否則返回1,并置errno。 參數(shù)說明:sock_fd 是socket函數(shù)返回的socket描述符;serv_addr是包含遠(yuǎn)端主機(jī)IP地址和端口號的指針;addrlen是遠(yuǎn)端地質(zhì)結(jié)構(gòu)的長度。 進(jìn)行客戶端程序設(shè)計(jì)無須調(diào)用bind(),因?yàn)檫@種情況下只需知道目的機(jī)器的IP地址,而客戶通過哪個(gè)端口與服務(wù)器建立連接并不需要關(guān)心, socket執(zhí)行體為你的程序自動(dòng)選擇一個(gè)未被占用的端口,并通知你的程序數(shù)據(jù)什么時(shí)候到端口。 connect函數(shù)啟動(dòng)和遠(yuǎn)端主機(jī)的直接連接。只有面向連接的客戶程序使用socket時(shí)才需要將此socket與遠(yuǎn)端主
10、機(jī)相連。無連接協(xié)議從不建立直接連接。面向連接的服務(wù)器也從不啟動(dòng)一個(gè)連接,它只是被動(dòng)的在協(xié)議端口監(jiān)聽客戶的請求。監(jiān)聽 listen函數(shù)使socket處于被動(dòng)的監(jiān)聽模式,并為該socket建立一個(gè)輸入數(shù)據(jù)隊(duì)列,將到達(dá)的服務(wù)請求保存在此隊(duì)列中,直到程序處理它們。 int listen(int sock_fd, int backlog); 功能說明:等待指定的端口的出現(xiàn)客戶端連接。調(diào)用成功返回0,否則,返回1,并置errno. 參數(shù)說明:sock_fd 是socket系統(tǒng)調(diào)用返回的socket 描述符; backlog指定在請求隊(duì)列中允許的最大請求數(shù),進(jìn)入的連接請求將在隊(duì)列中等待accept()接受
11、accept()函數(shù)讓服務(wù)器接收客戶的連接請求。在建立好輸入隊(duì)列后,服務(wù)器就調(diào)用accept函數(shù),然后睡眠并等待客戶的連接請求。 int accept(int sock_fd, void *addr, int *addrlen); 功能說明:用于接受客戶端的服務(wù)請求,成功返回新的套接字描述符,失敗返回1,并置errno。 參數(shù)說明:sock_fd是被監(jiān)聽的socket描述符,addr通常是一個(gè)指向sockaddr_in變量的指針,該變量用來存放提出連接請求服務(wù)的主機(jī)的信息(某臺主機(jī)從某個(gè)端口發(fā)出該請求);addrten通常為一個(gè)指向值為sizeof(struct sockaddr_in)的整型
12、指針變量。出現(xiàn)錯(cuò)誤時(shí)accept函數(shù)返回-1并置相應(yīng)的errno值。 首先,當(dāng)accept函數(shù)監(jiān)視的 socket收到連接請求時(shí),socket執(zhí)行體將建立一個(gè)新的socket,執(zhí)行體將這個(gè)新socket和請求連接進(jìn)程的地址聯(lián)系起來,收到服務(wù)請求的初始socket仍可以繼續(xù)在以前的 socket上監(jiān)聽,同時(shí)可以在新的socket描述符上進(jìn)行數(shù)據(jù)傳輸操作。結(jié)束傳輸 當(dāng)所有的數(shù)據(jù)操作結(jié)束以后,你可以調(diào)用close()函數(shù)來釋放該socket,從而停止在該socket上的任何數(shù)據(jù)操作: 2關(guān)鍵代碼解釋客戶端: #include #include #include #include #include #
13、include #include #define LISTEN_LEN 10int err,sd;char rd_buf100, wr_buf100;void *thread_read1(void *arg)while(1)memset(rd_buf,0,100);read(sd,rd_buf,100);printf(%sn,rd_buf);sleep(2);return NULL;void *thread_write1(void *arg)while(1)memset(wr_buf, 0, 100);scanf(%s, wr_buf);write(sd,wr_buf,sizeof(wr_bu
14、f);sleep(2);return NULL;int main()pthread_t tid1,tid2;int server_len,client_len;struct sockaddr_in server_ip,client_ip;sd = socket(AF_INET,SOCK_STREAM,0);if(sd 0)printf(socket failed! errno = %dn,errno);close(sd);return -1;server_ip.sin_family = AF_INET;server_ip.sin_port = htons(5678);server_ip.sin
15、_addr.s_addr = htonl(INADDR_ANY);memset(server_ip.sin_zero,0,8); err = connect(sd,(struct sockaddr *)(&server_ip),sizeof(struct sockaddr);if(err 0)printf(connect failed! errno = %dn,errno);close(sd);return -1;err = pthread_create(&tid1,NULL,thread_read1,NULL);if(err != 0)printf(thread_read1 creat fa
16、iled! errno = %dn,errno);close(sd);return -1;err = pthread_create(&tid2,NULL,thread_write1,NULL);if(err != 0)printf(thread_write1 creat failed! errno = %dn,errno);close(sd);return -1;pthread_join(tid1,NULL);pthread_join(tid2,NULL);close(sd);return 0 ; 服務(wù)器:#include #include #include #include #include
17、 #include #include #define LISTEN_LEN 10int i=0,err,sd,ad;char buf12100,buf21100;void *thread_read1(void *arg);void *thread_write1(void *arg);void *thread_read1(void *arg)while(1)read(ad,buf12,100);printf(%sn, buf12);sleep(2);return NULL;void *thread_write1(void *arg)while(1)memset(buf21, 0, 100);sc
18、anf(%s, buf21);write(ad,buf21,100);sleep(2);return NULL;int main()pthread_t tid1,tid2;int server_len,client_len;struct sockaddr_in server_ip,client_ip;sd = socket(AF_INET,SOCK_STREAM,0);if(sd 0)printf(socket failed! errno = %dn,errno);close(sd);return -1;server_ip.sin_family = AF_INET;server_ip.sin_
19、port = htons(5678);server_ip.sin_addr.s_addr = htonl(INADDR_ANY);memset(server_ip.sin_zero,0,8); err = bind(sd,(struct sockaddr *)(&server_ip),sizeof(struct sockaddr);if(err 0)printf(bind failed! errno = %dn,errno);close(sd);return -1;err = listen(sd,LISTEN_LEN);if(err 0)printf(listen failed! errno
20、= %dn,errno);close(sd);return -1;client_len = sizeof(struct sockaddr);while(1)ad = accept(sd,(struct sockaddr *)(&client_ip),&client_len);if(ad 0 )printf(accept failed! errno = %dn,errno);close(sd);return -1;err = pthread_create(&tid1,NULL,thread_read1,NULL);if(err != 0)printf(thread_read1 creat failed! errno = %dn,errno);close(sd);close(ad);return -1;err = pthread_create(&tid2,NULL,thread_write1,NULL);if(err != 0)printf(thread_write1 creat f
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 高中數(shù)學(xué)分層練習(xí)(壓軸題)06:函數(shù)與導(dǎo)數(shù)(30題)【含解析】
- 水池專項(xiàng)施工方案
- 洗手洗腳池施工方案
- 電梯施工方案模板
- 基于涉入理論的高爾夫球手地方依戀研究
- 6到12歲的感統(tǒng)訓(xùn)書籍
- consider的固定搭配和例句總結(jié)
- 2025年往年英語a b級試題及答案
- 燈火闌珊處高情商回復(fù)
- 4-氨基-丁酸叔丁酯醋酸鹽
- 日常采購維修合同范本
- 2024-2025年第二學(xué)期一年級語文教學(xué)進(jìn)度表
- 企業(yè)員工職務(wù)犯罪預(yù)防
- 2025年貴州省高職單招醫(yī)學(xué)類職業(yè)技能測試題庫及答案(備考刷題)
- 5《水污染》教學(xué)設(shè)計(jì)-2023-2024學(xué)年科學(xué)六年級下冊冀人版
- 2025年安徽電氣工程職業(yè)技術(shù)學(xué)院高職單招職業(yè)技能測試近5年??及鎱⒖碱}庫含答案解析
- 幼兒園開學(xué)教職工安全教育培訓(xùn)
- 2025-2030年中國發(fā)酵豆粕行業(yè)運(yùn)行態(tài)勢及投資前景規(guī)劃研究報(bào)告
- 酒店建設(shè)項(xiàng)目施工總承包合同
- 2025年政府采購代理機(jī)構(gòu)考試題庫及答案
- 第14課《第一次世界大戰(zhàn)》中職高一下學(xué)期高教版(2023)世界歷史全一冊
評論
0/150
提交評論