




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、實驗七:網(wǎng)絡(luò)編程l 實驗?zāi)康模簩W(xué)會Linux的socket套接字網(wǎng)絡(luò)編程,熟悉使用TCP傳輸協(xié)議的網(wǎng)絡(luò)編程流程l 實驗要求:編寫使用TCP協(xié)議的服務(wù)器程序和客戶端程序,客戶端向服務(wù)器發(fā)送字符串,服務(wù)器打印收到的字符串l 實驗器材:軟件:安裝了Linux的vmware虛擬機硬件:PC機一臺l 實驗步驟:1、編寫服務(wù)器端代碼tcp_server.c#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <netdb.h>
2、#include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #define portnumber 3333int main(int argc, char *argv) int sockfd,new_fd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; int sin_size; int nbytes;char buffer1024;/*1、服務(wù)器創(chuàng)建sockfd描述符 */ if(sockfd=s
3、ocket(AF_INET,SOCK_STREAM,0)=-1)/ AF_INET:IPV4;SOCK_STREAM:TCP fprintf(stderr,"Socket error:%sna",strerror(errno); exit(1); /* 2、服務(wù)器端填充 sockaddr結(jié)構(gòu) */ bzero(&server_addr,sizeof(struct sockaddr_in); / 初始化,置0server_addr.sin_family=AF_INET; / Internetserver_addr.sin_addr.s_addr=htonl(INADD
4、R_ANY); / (將本機器上的long數(shù)據(jù)轉(zhuǎn)化為網(wǎng)絡(luò)上的long數(shù)據(jù))服務(wù)器程序能運行在任何ip的主機上/server_addr.sin_addr.s_addr=inet_addr("192.168.1.1"); /用于綁定到一個固定IP,inet_addr用于把數(shù)字加格式的ip轉(zhuǎn)化為整形ipserver_addr.sin_port=htons(portnumber); / (將本機器上的short數(shù)據(jù)轉(zhuǎn)化為網(wǎng)絡(luò)上的short數(shù)據(jù))端口號/* 3、綁定地址結(jié)構(gòu)體 */ if( bind(sockfd, &server_addr,sizeof(server_add
5、r)<0)printf(“bind error!”);exit(-1);/* 4、設(shè)置監(jiān)聽允許連接的最大客戶端數(shù) */ if( listen( sockfd, 0)<0)printf(“l(fā)isten error!”);exit(-1);while(1) /* 5、服務(wù)器阻塞,直到客戶程序建立連接 */ sin_size=sizeof(struct sockaddr_in); if(new_fd=accept(sockfd,& server_addr,&sin_size)<0)printf(“accept error!”);exit(-1); /連接成功后打印客
6、戶端IPfprintf(stderr,"Server get connection from %sn",inet_ntoa(client_addr.sin_addr); / 將網(wǎng)絡(luò)地址轉(zhuǎn)換成.字符串 /6、read()函數(shù)讀取客戶端發(fā)送的消息nbytes=read(new_fd,buffer,1024);buffernbytes='0'printf("Server received %sn",buffer);/* 這個通訊已經(jīng)結(jié)束 */ close(new_fd); /* 循環(huán)下一個 */ /* 結(jié)束通訊 */ close(sockfd)
7、; exit(0); /*完整程序*#include <stdio.h>#include <stdlib.h>#include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include<arpa/inet.h>/inet_ntoa()#include <unistd.h>/rea
8、d(),close()#define portnumber 3333int main(int argc, char *argv) int sockfd,new_fd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; int sin_size; int nbytes;char buffer1024;/*1、服務(wù)器創(chuàng)建sockfd描述符 */ if(sockfd=socket(AF_INET,SOCK_STREAM,0)=-1) fprintf(stderr,"Socket error:%sna",
9、strerror(errno); exit(1); /* 2、服務(wù)器端填充 sockaddr結(jié)構(gòu) */ bzero(&server_addr,sizeof(struct sockaddr_in); server_addr.sin_family=AF_INET; server_addr.sin_addr.s_addr=htonl(INADDR_ANY);server_addr.sin_port=htons(portnumber); /* 3、綁定地址結(jié)構(gòu)體 */ if( bind(sockfd, (struct sockaddr *)(&server_addr),sizeof(s
10、truct sockaddr)<0)printf("bind error!");exit(-1);/* 4、設(shè)置監(jiān)聽允許連接的最大客戶端數(shù) */ if( listen( sockfd,5)<0)printf("listen error!");exit(-1);while(1) /* 5、服務(wù)器阻塞,直到客戶程序建立連接 */ sin_size=sizeof(struct sockaddr_in); if(new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_si
11、ze)<0)printf("accept error!");exit(-1); /連接成功后打印客戶端IP if(fork=0) /fork(),創(chuàng)建子進(jìn)程,多個進(jìn)程不需等候fprintf(stderr,"server get connection from %sn",inet_ntoa(client_addr.sin_addr); /6、read()函數(shù)讀取客戶端發(fā)送的消息nbytes=read(new_fd,buffer,1024);buffernbytes='0'printf("Server received %sn
12、",buffer);/* 這個通訊已經(jīng)結(jié)束 */ close(new_fd); else close(new_fd); /結(jié)束父進(jìn)程/* 循環(huán)下一個 */ /* 結(jié)束通訊 */ return 0; */2、編寫客戶端代碼tcp_client.c#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <neti
13、net/in.h> #include <sys/socket.h> #define portnumber 3333int main(int argc, char *argv) int sockfd; char buffer1024; struct sockaddr_in server_addr; struct hostent *host; /* 1、客戶程序開始建立 sockfd描述符 */ if(sockfd=socket(AF_INET,SOCK_STREAM,0)=-1) /AF_INET:Internet;SOCK_STREAM:TCP fprintf(stderr,
14、"Socket Error:%san",strerror(errno); exit(1); /* 2、客戶程序填充服務(wù)端的資料 */ bzero(&server_addr,sizeof(server_addr); / 初始化,置0server_addr.sin_family=AF_INET; / IPV4server_addr.sin_port=htons(portnumber); / (將本機器上的short數(shù)據(jù)轉(zhuǎn)化為網(wǎng)絡(luò)上的short數(shù)據(jù))端口號server_addr.sin_addr.s_addr=htonl(INADDR_ANY);/* 3、connect函
15、數(shù),客戶程序發(fā)起連接請求 */ if( connect( sockfd, &server_addr, sizeof(server_addr)<0)printf(“connet error!”);exit(-1);z/* 連接成功了 */ printf("Please input char:n");/* 等待終端輸入數(shù)據(jù) */fgets(buffer,1024,stdin); /4、write函數(shù)發(fā)送buffer數(shù)據(jù)write( sockfd,buffer,strlen(buffer);/* 結(jié)束通訊 */ close(sockfd); exit(0); /*完
16、整程序*#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include<arpa/inet.h>/inet_ntoa()#include <unistd.h>/read(),close()#
17、define portnumber 3333int main(int argc, char *argv) int sockfd; char buffer1024; struct sockaddr_in server_addr; struct hostent *host; /* 1、客戶程序開始建立 sockfd描述符 */ if(sockfd=socket(AF_INET,SOCK_STREAM,0)=-1) /AF_INET:Internet;SOCK_STREAM:TCP fprintf(stderr,"Socket Error:%san",strerror(errno
18、); exit(1); /* 2、客戶程序填充服務(wù)端的資料 */ bzero(&server_addr,sizeof(server_addr); / 初始化,置0server_addr.sin_family=AF_INET; / IPV4server_addr.sin_port=htons(portnumber); / (將本機器上的short數(shù)據(jù)轉(zhuǎn)化為網(wǎng)絡(luò)上的short數(shù)據(jù))端口號server_addr.sin_addr.s_addr=htonl(INADDR_ANY);/* 3、connect函數(shù),客戶程序發(fā)起連接請求 */ if(connect( sockfd, (struct
19、sockaddr *)(&server_addr), sizeof(server_addr)<0)printf("connet error!");exit(-1);/* 連接成功了 */ printf("Please input char:n");/* 等待終端輸入數(shù)據(jù) */fgets(buffer,1024,stdin); /4、write函數(shù)發(fā)送buffer數(shù)據(jù)write( sockfd,buffer,strlen(buffer);/* 結(jié)束通訊 */ close(sockfd); exit(0); return 0;*/3、編譯并運行
20、應(yīng)用程序先運行服務(wù)器程序tcp_server,然后在另一個終端中運行客戶端程序tcp_client。從運行情況可以看出,在沒有客戶端連接上來時服務(wù)器程序阻塞在accept函數(shù)上,等待連接,當(dāng)有客戶端程序連接上來時,阻塞在read函數(shù)上,等待讀取消息。客戶端發(fā)送一條消息后結(jié)束,服務(wù)器讀取消息并打印出來,繼續(xù)等待新的連接l 上機報告要求:上面的TCP服務(wù)器每次只能處理一次客戶端請求,嘗試將他改寫成并發(fā)TCP服務(wù)器,即可以處理多個客戶端請求,測試成功后將代碼寫入實驗報告。/*#include<sys/socket.h>int scoket(int domain,int type,int
21、protocol)socket函數(shù)對應(yīng)于普通文件的打開操作。普通文件的打開操作返回一個文件描述字,而socket()用于創(chuàng)建一個socket描述符(socket descriptor),它唯一標(biāo)識一個socket。這個socket描述字跟文件描述字一樣,后續(xù)的操作都有用到它,把它作為參數(shù),通過它來進(jìn)行一些讀寫操作。正如可以給fopen的傳入不同參數(shù)值,以打開不同的文件。創(chuàng)建socket的時候,也可以指定不同的參數(shù)創(chuàng)建不同的socket描述符,socket函數(shù)的三個參數(shù)分別為:domain:即協(xié)議域,又稱為協(xié)議族(family)。常用的協(xié)議族有,AF_INET (IPv4 英特網(wǎng)域)、AF_IN
22、ET6 (IPv6英特網(wǎng)域)、AF_LOCAL(或稱AF_UNIX,Unix域socket)、AF_ROUTE等等。協(xié)議族決定了socket的地址類型,在通信中必須采用對應(yīng)的地址,如AF_INET決定了要用ipv4地址(32位的)與端口號(16位的)的組合、AF_UNIX決定了要用一個絕對路徑名作為地址。type:指定socket類型。常用的socket類型有,SOCK_STREAM(流式套接字 TCP)、SOCK_DGRAM(數(shù)據(jù)報套接字 UDP)、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等(socket的類型有哪些?)。protocol:故名思意,就是指定協(xié)
23、議。(按給定的域和套接字類型選擇默認(rèn)協(xié)議,通常為0)常用的協(xié)議有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它們分別對應(yīng)TCP傳輸協(xié)議、UDP傳輸協(xié)議、STCP傳輸協(xié)議、TIPC傳輸協(xié)議當(dāng)我們調(diào)用socket創(chuàng)建一個socket時,返回的socket描述字它存在于協(xié)議族(address family,AF_XXX)空間中,但沒有一個具體的地址。如果想要給它賦值一個地址,就必須調(diào)用bind()函數(shù),否則就當(dāng)調(diào)用connect()、listen()時系統(tǒng)會自動隨機分配一個端口。字節(jié)序轉(zhuǎn)換不同類型的CPU對變量的字節(jié)存儲順序可能不同:有的系
24、統(tǒng)是大端字節(jié)序,即高位在低地址,即低位在高地址,而有的系統(tǒng)如x86是小端字節(jié)序,即低位在低地址,高位在高地址,而網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)順序是一定要統(tǒng)一的,所有當(dāng)內(nèi)部字節(jié)存儲順序和網(wǎng)絡(luò)字節(jié)序(大端字節(jié)序)不同時,就一定要進(jìn)行轉(zhuǎn)換unsigned long htonl(unsigned long hostlong);unsigned short htons(unsigned short hostshort);unsigned long ntohl(unsigned long netlong);unsigned short ntohs(unsigned short netshort);htonl()函數(shù)是將
25、32位無符號長整形數(shù)據(jù)從主機字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序返回值:htonl()返回一個網(wǎng)絡(luò)字節(jié)順序的值。htons()函數(shù)是將16位無符號短整形數(shù)據(jù)從主機字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序返回值:htons()返回一個網(wǎng)絡(luò)字節(jié)順序的值。htonl()/htons()函數(shù)是將32/16位整形數(shù)據(jù)從網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換為主機字節(jié)序通用地址格式struct sockaddr unsigned short sa_family; /* 地址族, AF_xxx */char sa_data14; /* 14字節(jié)的協(xié)議地址*/;sa_family:協(xié)議族,采用“AF_xxx”形式,如AF_INET(IP協(xié)議
26、族)(domain)sa_data:1包含了一些遠(yuǎn)程電腦的地址、端口和套接字的數(shù)目,它里面的數(shù)據(jù)是夾雜在一起的struct sockaddr_in short int sin_family; /* 地址族 */unsigned short int sin_port; /* 端口號 */struct in_addr sin_addr; /* Internet地址 */unsigned char sin_zero8; /* 與struct sockaddr一樣的長度 */;IP地址通常由數(shù)字加點(192.168.0.1)的形式表示,而struct in_addr中使用的IP地址是由32位的整數(shù)表示
27、的,為了轉(zhuǎn)換我們可以使用下面兩個函數(shù):in_addr_t inet_addr(const char* strptr); 將一個點分十進(jìn)制的IP轉(zhuǎn)換成一個長整數(shù)型數(shù)(u_long類型)char *inet_ntoa(struct in_addr in)函數(shù)里面a代表ascii,n代表networkinet_aton是將a.b.c.d形式的IP轉(zhuǎn)換為32位的IP,存儲在inp指針里面,inet_ntoa是將32位IP轉(zhuǎn)換為a.b.c.d的格式struct in_addr unsigned long s_addr;#include<sys/socket.h>int bind(int so
28、ckfd, const struct sockaddr *addr, socklen_t addrlen);函數(shù)的三個參數(shù)分別為:sockfd:即socket描述字,它是通過socket()函數(shù)創(chuàng)建了,唯一標(biāo)識一個socket。bind()函數(shù)就是將給這個描述字綁定一個名字。addr:一個const struct sockaddr *指針,指向要綁定給sockfd的協(xié)議地址。這個地址結(jié)構(gòu)根據(jù)地址創(chuàng)建socket時的地址協(xié)議族的不同而不同。 addrlen:對應(yīng)的是地址的長度。(通常設(shè)為scokaddr結(jié)構(gòu)的長度)返回值:成功返回0,否則返回-1如果作為一個服務(wù)器,
29、在調(diào)用socket()、bind()之后就會調(diào)用listen()來監(jiān)聽這個socket,如果客戶端這時調(diào)用connect()發(fā)出連接請求,服務(wù)器端就會接收到這個請求。#include<sys/socket.h>int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);sockfd:為客戶端的socket描述字,addr:為服務(wù)器的socket地址(為指向sockaddr結(jié)構(gòu)的指針),addrlen:為socket地址的長度。客戶端通過調(diào)用connect函數(shù)來建立與TCP服務(wù)器的連接。返回值:0成功,-1錯誤#include<sys/socket.h>int listen(int sockfd, int backlog);sockfd,:為要監(jiān)聽的socket描述字,backlog:為相應(yīng)socket可以排隊的最大連接個數(shù)。(系統(tǒng)默認(rèn)值為20,0表示無限制)socket()函數(shù)創(chuàng)建的socket
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度木材購銷合同模板(含木材紋理應(yīng)用)
- 二零二五年度文化產(chǎn)業(yè)借款協(xié)議書
- 加油站合伙經(jīng)營協(xié)議書(2025年執(zhí)行)
- 二零二五年度家庭贍養(yǎng)老人費用分?jǐn)偧梆B(yǎng)老護理協(xié)議
- 2025年度智能健身中心全新會員卡儲值服務(wù)協(xié)議
- 二零二五年度網(wǎng)絡(luò)短視頻影視作品演員簽約合同
- 二零二五年度老年用品銷售提成及養(yǎng)老服務(wù)協(xié)議
- 二零二五年度公司單位員工保密協(xié)議與勞動合同合并文本
- 二零二五年度酒店客房租賃與旅游導(dǎo)游服務(wù)合同
- 二零二五年度服裝零售店鋪轉(zhuǎn)讓協(xié)議書模板
- 股骨頸骨折ppt精品
- 2023年江蘇農(nóng)牧科技職業(yè)學(xué)院單招職業(yè)適應(yīng)性測試題庫及答案解析
- 毛澤東詩詞鑒賞分析
- 小學(xué)數(shù)學(xué)-納稅教學(xué)設(shè)計學(xué)情分析教材分析課后反思
- 量具檢具清單
- YY/T 1833.2-2022人工智能醫(yī)療器械質(zhì)量要求和評價第2部分:數(shù)據(jù)集通用要求
- 光催化原理(經(jīng)典)課件
- 如何上好一堂課(課件)
- 動車組列車乘務(wù)人員實務(wù)教材課件
- 西方文藝?yán)碚撌肪x文獻(xiàn)課件
評論
0/150
提交評論