![第3章 基本TCP套接口編程_第1頁](http://file2.renrendoc.com/fileroot_temp3/2021-10/16/702a79ee-f222-4be1-9a60-e7bb10f7788f/702a79ee-f222-4be1-9a60-e7bb10f7788f1.gif)
![第3章 基本TCP套接口編程_第2頁](http://file2.renrendoc.com/fileroot_temp3/2021-10/16/702a79ee-f222-4be1-9a60-e7bb10f7788f/702a79ee-f222-4be1-9a60-e7bb10f7788f2.gif)
![第3章 基本TCP套接口編程_第3頁](http://file2.renrendoc.com/fileroot_temp3/2021-10/16/702a79ee-f222-4be1-9a60-e7bb10f7788f/702a79ee-f222-4be1-9a60-e7bb10f7788f3.gif)
![第3章 基本TCP套接口編程_第4頁](http://file2.renrendoc.com/fileroot_temp3/2021-10/16/702a79ee-f222-4be1-9a60-e7bb10f7788f/702a79ee-f222-4be1-9a60-e7bb10f7788f4.gif)
![第3章 基本TCP套接口編程_第5頁](http://file2.renrendoc.com/fileroot_temp3/2021-10/16/702a79ee-f222-4be1-9a60-e7bb10f7788f/702a79ee-f222-4be1-9a60-e7bb10f7788f5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、Tcp套接字編程知識點: 使用TCP套接字編程的基本步驟 實現(xiàn)TCP套接字編程的基本函數(shù) 服務(wù)器的3種異常情況TCP套接字編程(cont.)#include int socket(int family, int type, int protocol) 返回:非負(fù)套接字(sockfd)成功;-1出錯。功能:指定協(xié)議類型功能:指定協(xié)議類型參數(shù)說明:參數(shù)說明:family:協(xié)議族;type:套接字類型; protocol:一般為0,除原始套接字外。 family typeAF_INET IPv4協(xié)議SOCK_STREAM 字節(jié)流套接口AF_INET6IPv6協(xié)議SOCK_DGRAM 數(shù)據(jù)報套接口AF
2、_LOCALunix域協(xié)議SOCK_RAW 原始套接口AF_ROUTE 路由套接口AF_KEY 密鑰套接口基本套接字函數(shù)socket AF_INET AF_INET6 AF_LOCAL AF_ROUTE AF_KEY SOCK_STREAM TCP TCP Yes SOCK_DGRAM UDP UDP Yes SOCK_RAW IPv4 IPv6 Yes Yes Protocol:指明此socket請求所使用的協(xié)議,可以使用如下相關(guān)符號常數(shù)來表示。IPPROTO_TCP:表示TCP協(xié)議IPPROTO_UDP:表示UDP協(xié)議調(diào)用Socket()函數(shù)的過程socket 函數(shù)指定了協(xié)議族函數(shù)指定了協(xié)
3、議族(IPv4、IPv6或或unix)和套接口類型和套接口類型(字節(jié)流、數(shù)據(jù)報或原字節(jié)流、數(shù)據(jù)報或原始套接口始套接口)。但并沒有指定本地協(xié)議地址或遠(yuǎn)程協(xié)議地址。但并沒有指定本地協(xié)議地址或遠(yuǎn)程協(xié)議地址。理解理解socket socket使用 Unix 文件描述符 (file descriptor) 和其他程序通訊的方式。 Unix 程序在執(zhí)行任何形式的 I/O 的時候,程序是在讀或者寫一個文件描述符。一個文件描述符只是一個和打開的文件相關(guān)聯(lián)的整數(shù)。這個文件可能是一個網(wǎng)絡(luò)連接,F(xiàn)IFO,管道,終端,磁盤上的文件或者什么其他的東西。Unix 中所有的東西是文件!因此,與 Internet 上別的程序
4、通訊的時候,要通過文件描述符。 利用系統(tǒng)調(diào)用 socket()得到網(wǎng)絡(luò)通訊的文件描述符。他返回套接口描述符 (socket descriptor),然后再通過他來調(diào)用 send() 和 recv()。那么為什么不用一般的調(diào)用那么為什么不用一般的調(diào)用 read() 和和 write() 來通過套接口通訊?來通過套接口通訊? 簡單的答案是:可以使用一般的函數(shù)! 詳細(xì)的答案是:使用 send() 和 recv() 讓你更好的控制數(shù)據(jù)傳輸。#include #include int bind(int sockfd, const struct sockaddr *addr, socklen_len ad
5、drlen) 返回:0成功;-1出錯并置errno功能:給套接口分配一個本地協(xié)議地址。功能:給套接口分配一個本地協(xié)議地址。參數(shù)說明:參數(shù)說明: sockfd是套接字函數(shù)返回的套接字描述符;addr參數(shù)是指向特定協(xié)議的地址結(jié)構(gòu)的指針,指定用于通信的本地協(xié)議地址,這是通用地址(網(wǎng)際協(xié)議)。 addrlen是該套接字地址結(jié)構(gòu)的長度。 該函數(shù)指明套接字將使用本地的哪一個協(xié)議端口進(jìn)行數(shù)據(jù)傳送(IP地址和端口號)。 一般而言,服務(wù)器調(diào)用此函數(shù),而客戶則很少調(diào)用它。 基本套接字函數(shù)bind 綁定地址時,可以指定地址和端口號,也可以指定其中之一,甚至一個也不指定。通配地址:INADDR_ANY,其值一般為0,
6、它通知內(nèi)核選擇IP地址。 若指定端口號為0,調(diào)用函數(shù)bind時,內(nèi)核選擇一個臨時端口(在實際中,端口號都要指定);但若指定一個通配IP地址,則直到套接字已連接(TCP)或數(shù)據(jù)報已在套接字上發(fā)出(UDP),內(nèi)核才選擇一個本地IP地址。 表中給出了調(diào)用bind()函數(shù)時,IP地址和端口號的取值及其對應(yīng)的結(jié)果。IP地址地址 端口端口結(jié)果結(jié)果通配地址 0內(nèi)核選擇IP地址和端口號通配地址 非0內(nèi)核選擇IP地址,進(jìn)程指定端口本地IP 0進(jìn)程指定IP地址,內(nèi)核選擇端口本地IP 非0進(jìn)程指定IP地址和端口號struct sockaddr_in addr;int port = 1234;int opt = SO
7、_REUSEADDR;setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt); bzero(&server,sizeof(server);addr.sin_family = AF_INET;addr.sin_addr.s_addr = htonl(INADDR_ANY);addr.sin_port = htons(port);if (bind(fd, (struct sockaddr *)&addr, sizeof(addr) = -1)/* 錯誤處理 */bind函數(shù)的用法#include int listen(int sockf
8、d, int backlog) 返回:0成功;-1出錯并置errno值;功能:將未連接主動套接口的轉(zhuǎn)換為被動套接口,指示內(nèi)核接受功能:將未連接主動套接口的轉(zhuǎn)換為被動套接口,指示內(nèi)核接受對該套接口的連接請求對該套接口的連接請求.函數(shù)listen僅被服務(wù)器調(diào)用,它完成兩件事情: 函數(shù)listen將未連接的套接字轉(zhuǎn)化成被動套接字,指示內(nèi)核應(yīng)接受指向此套接字的連接請求; 函數(shù)的第二個參數(shù)規(guī)定了內(nèi)核為此套接字排隊的最大連接個數(shù);基本套接字函數(shù)listen三路握手過程客戶服務(wù)器Connect調(diào)用在未完成隊列建立條目SYN JSYN K, ack J+1ack K+1該條目從未完成隊列移至已完成隊列,acc
9、ept阻塞Connect返回TCP三路握手和監(jiān)聽套接口的兩個隊列對于給定的監(jiān)聽套接字,內(nèi)核要維護(hù)兩個隊列: 未完成連接隊列:為每個請求建立連接的SYN分節(jié)開設(shè)一個條目,服務(wù)器正等待完成TCP三次握手,當(dāng)前的套接字處在SYNRCVD狀態(tài); 已完成連接隊列:為每個已完成TCP三次握手的客戶端開設(shè)一個條目。當(dāng)前的套接字狀態(tài)為ESTABLISHED。 兩個隊列之和不超過backlog;三路握手完成兩隊列之和不能超過backlog已完成連接隊列(ESTABLISHED狀態(tài))未完成連接隊列(SYN_RCVD狀態(tài))新到達(dá)的SYN分節(jié)服務(wù)器TCPacceptTCP為監(jiān)聽套接口維護(hù)的兩個隊列為監(jiān)聽套接口維護(hù)的兩
10、個隊列另外幾點說明:另外幾點說明: 不同的實現(xiàn)對backlog有不同的解釋,如源自Berkeley的實現(xiàn)將backlog增加一個模糊因子,把它乘以1.5,再作為兩個隊列之和; 不要把backlog定義為0,因為有些實現(xiàn)允許1個連接排隊,而有些實現(xiàn)不允許有連接排隊; 當(dāng)一個客戶SYN到達(dá)時,若兩個隊列都是滿的,tcp就忽略此分節(jié),且不發(fā)送RST。這是因為,這種情況是暫時的,客戶tcp將重發(fā)SYN,期望不久的將來就能在隊列中找到空閑條目。#include #include int connect(int sockfd, const struct sockaddr *addr, socklen_t
11、addrlen); 返回:0成功;-1出錯;功能:建立與功能:建立與TCP服務(wù)器的連接服務(wù)器的連接參數(shù)說明:參數(shù)說明:/sockfd 是系統(tǒng)調(diào)用 socket() 返回的套接口文件描述符/serv_addr 是保存著目的地端口和 IP 地址的數(shù)據(jù)結(jié)構(gòu) struct sockaddr/addrlen 設(shè)置為 sizeof(struct sockaddr) 函數(shù)connect激發(fā)TCP的三路握手過程;僅在成功或出錯返回;基本套接字函數(shù)connect錯誤有以下幾種情況錯誤有以下幾種情況: 如果客戶沒有收到SYN分節(jié)的響應(yīng)(總共75秒,這之間需要可能需要重發(fā)若干次SYN),則返回ETIMEDOUT。
12、如果對客戶的SYN的響應(yīng)是RST,則表明該服務(wù)器主機(jī)在指定的端口上沒有進(jìn)程在等待與之相連。函數(shù)返回錯誤ECONNREFUSED; 如果客戶發(fā)出的SYN在中間路由器上引發(fā)一個目的地不可達(dá)ICMP錯誤,客戶上的內(nèi)核保存此消息,并按第一種情況,連續(xù)發(fā)送SYN,直到規(guī)定時間,返回保存的消息(即ICMP錯誤)作為EHOSTUNREACH或ENETUNREACH錯誤返回給進(jìn)程。#include int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen); 返回:非負(fù)描述字(connfd)OK;-1出錯;功能功能:在已完成隊列頭返
13、回下一個已完成的連接。在已完成隊列頭返回下一個已完成的連接。 accept函數(shù)由TCP服務(wù)器調(diào)用;從已完成連接隊列頭返回下一個已完成連接;如果該隊列空,則進(jìn)程進(jìn)入睡眠狀態(tài)。 函數(shù)返回的套接字為已連接套接字,應(yīng)與監(jiān)聽套接字區(qū)分開來 該函數(shù)最多:一個既可能是新套接字也可能是錯誤指示的整數(shù),一個客戶進(jìn)程的協(xié)議地址(由cliaddr所指),以及該地址的大小(這后兩個參數(shù)是值結(jié)果參數(shù));也就是說,服務(wù)器可以通過參數(shù)cliaddr來得到請求連接并獲得成功的客戶的地址和端口號;基本套接字函數(shù)accept幾點說明:幾點說明: 調(diào)用成功時返回: 1. cliaddr: 客戶進(jìn)程的協(xié)議地址和地址大小 2. 新套接
14、口描述字(已連接套接口描述字) , 監(jiān)聽套接口描述字 listening socket descriptor一個給定的服務(wù)器常常是只生成一個監(jiān)聽套接口, 且一直存在,直到該服務(wù)器關(guān)閉。 已連接套接口描述字connected socket descriptor內(nèi)核為每個被接受的客戶連接創(chuàng)建了一個已連接套接口。當(dāng)服務(wù)器完成某客戶的服務(wù)時,關(guān)閉已連接套接口。 1024以下的端口:超級用戶使用#include int close(int sockfd); 返回:0OK;-1出錯; close函數(shù)缺省功能是將套接字做上“已關(guān)閉”標(biāo)記,并立即返回到進(jìn)程。這個套接字不能再為該進(jìn)程所用(即不能再接收和發(fā)送數(shù)據(jù)
15、,不能作為函數(shù)read和write的參數(shù))。 正常情況下,close將引發(fā)向TCP的四分節(jié)終止序列,但在終止前將發(fā)送已排隊的數(shù)據(jù); 如果套接字描述符訪問計數(shù)在調(diào)用close后大于0(在多個進(jìn)程共享同一個套接字的情況下),則不會引發(fā)TCP終止序列(即不會發(fā)送FIN分節(jié));基本套接字函數(shù)close#include int shutdown(int sockfd, int howto); 返回:0OK;-1出錯,并置相應(yīng)的errno的值; 該函數(shù)立即發(fā)送FIN分節(jié)(無論其訪問計數(shù)是否大于0)。shutdown根據(jù)參數(shù)howto關(guān)閉指定方向的數(shù)據(jù)傳輸; SHUT_RD:關(guān)閉連接的讀這一半,不再接收套接
16、字中的數(shù)據(jù)且現(xiàn)留在接收緩沖區(qū)的數(shù)據(jù)作廢; SHUT_WR :關(guān)閉連接的寫這一半(半關(guān)閉),當(dāng)留在套接字發(fā)送緩沖區(qū)中的數(shù)據(jù)都被發(fā)送,后跟tcp連接終止序列,不管訪問計數(shù)是否大于0;此后將不能在執(zhí)行對套接字的任何寫操作; SHUT_RDWR:連接的讀、寫都關(guān)閉,這等效于調(diào)用shutdown兩次,一次調(diào)用是用SHUT_RD,第二次用SHUT_WR?;咎捉幼趾瘮?shù)-shutdown數(shù)據(jù)數(shù)據(jù)FIN數(shù)據(jù)和FIN的確認(rèn)數(shù)據(jù)數(shù)據(jù)FIN數(shù)據(jù)和FIN的確認(rèn)writewriteshutdownRead返回大于0Read返回大于0Read返回0writewritecloseRead返回大于0Read返回0Read返回
17、大于0客戶服務(wù)器調(diào)用shutdown關(guān)閉一半TCP連接#include int write(int fd, char *buf, int len); 返回:大于0讀寫字節(jié)大??;-1出錯; 調(diào)用函數(shù)write,有如下幾種情況: 套接字發(fā)送緩沖區(qū)有足夠空間,返回發(fā)送的字節(jié)數(shù); tcp協(xié)議接收到RST數(shù)據(jù),返回1,同時errno為ECONNRESET; ; 進(jìn)程阻塞過程中接收到信號,返回1,同時errno為EINTR。write(connfd,buff,strlen(buff);基本套接字函數(shù)write#include int read(int fd, char *buf, int len);返回:
18、大于0讀寫字節(jié)大?。?1出錯;調(diào)用函數(shù)read時,有如下幾種情況:套接字接收緩沖區(qū)接收數(shù)據(jù),返回接收到的字節(jié)數(shù);tcp協(xié)議收到FIN數(shù)據(jù),返回0;tcp協(xié)議收到RST數(shù)據(jù),返回1,同時errno為ECONNRESET;進(jìn)程阻塞過程中接收到信號,返回1,同時errno為EINTR。read(connfd,buff,strlen(buff);基本套接字函數(shù)read#include #include ssize_t send (int fd, const void *msg, size_t len, int flags); 返回:非0發(fā)送成功的數(shù)據(jù)長度;-1出錯; flags 是傳輸控制標(biāo)志,其值定
19、義如下: 0:常規(guī)操作,如同write()函數(shù) MSG_OOB,發(fā)送帶外數(shù)據(jù)(TCP緊急數(shù)據(jù))。 MSG_DONTROUTE:忽略底層協(xié)議的路由設(shè)置,只能將數(shù)據(jù)發(fā)送給與發(fā)送機(jī)處在同一個網(wǎng)絡(luò)中的機(jī)器上。 MSG_DONTWAIT:打開非阻塞模式(了解就OK),執(zhí)行I/O操作,再關(guān)閉非阻塞模式。數(shù)據(jù)傳輸函數(shù)send#include #include ssize_t recv(int fd, void *buf ,size_t len, int flags); 返回:大于0表示成功接收的數(shù)據(jù)長度;0: 對方已關(guān)閉,-1:出錯。 flags是傳輸控制標(biāo)志,其值定義如下: 0:常規(guī)操作,如同read()
20、函數(shù); MSG_PEEK:只查看數(shù)據(jù)而不讀出數(shù)據(jù),后續(xù)讀操作仍然能讀出所查看的該數(shù)據(jù); MSG_OOB:忽略常規(guī)數(shù)據(jù),而只讀帶外數(shù)據(jù); MSG_WAITALL:recv函數(shù)只有在將接收緩沖區(qū)填滿(也就是len的值)后才返回。 MSG_DONTWAIT:將單個I/O操作設(shè)為非阻塞模式,執(zhí)行I/O操作,然后關(guān)閉非阻塞標(biāo)志。數(shù)據(jù)傳輸函數(shù)recv 功能:派生新進(jìn)程 create new process 定義:#include pid_t fork (void); 在子進(jìn)程中返回0,在父進(jìn)程中返回子進(jìn)程的進(jìn)程ID 出錯時返回 1,調(diào)用一次返回兩次fork 函數(shù) fork的典型應(yīng)用(多線程): 1一個進(jìn)程
21、可為自己創(chuàng)建一個拷貝。當(dāng)一個拷貝處理一個操作時,其他的拷貝可以執(zhí)行其他的任務(wù)。這是非常典型的網(wǎng)絡(luò)服務(wù)器。 2一個進(jìn)程想執(zhí)行其他的程序,由于創(chuàng)建新進(jìn)程的唯一方法是調(diào)用fork,進(jìn)程首先調(diào)用fork來生成一個拷貝,然后其中一個拷貝(通常為子進(jìn)程)調(diào)用exec 來代替自己去執(zhí)行新程序。 socket() -得到文件描述符! bind() -我們在哪個端口? connect() -Hello! listen() -有人給我打電話嗎? accept() -Thank you for calling port 3490. send() 和 recv() -Talk to me, baby! sendto(
22、) 和 recvfrom() -Talk to me, DGRAM-style close() 和 shutdown() -滾開! getpeername() -你是誰? gethostname() -我是誰? DNS -你說“白宮”,我說 198.137.240.100簡而言之簡而言之實現(xiàn)TCP套接字基本步驟分為服務(wù)器端和客戶端兩部分:服務(wù)器端 創(chuàng)建套接字; 綁定套接字; 設(shè)置套接字為監(jiān)聽模式,進(jìn)入被動接受連接狀態(tài); 接受請求,建立連接 讀寫數(shù)據(jù)終止連接TCP套接字編程客戶端步驟 創(chuàng)建套接字 與遠(yuǎn)程服務(wù)器建立連接 讀/寫數(shù)據(jù);終止連接TCP套接字編程(cont.)int main(void)
23、int sockfd,connect_sock;if(sockfd=socket(AF_INET,SOCK_STREAM,0)=-1) perror(“create socket failed.”);exit(-1);/* bind sockfd to some address */* listen */loop if(connect_sock=accept(sockfd,NULL,NULL)=-1) perror(“Accept error.”); exit(-1); /* read and process request */close(connect_sock); close(sockf
24、d);TCP服務(wù)器模板/* include some header files */int main(void)int sockfd;if(sockfd=socket(AF_INET,SOCK_STREAM,0)=-1)perror(“Create socket failed.”);exit(-1);/* connect to server */* send requst and receive response */close(sockfd);TCP客戶模板 采用客戶/服務(wù)器模式,完成下列功能: 客戶根據(jù)用戶提供的IP地址,連接相應(yīng)的服務(wù)器; 服務(wù)器等待客戶的連接,一旦連接成功,則顯示客戶的IP地址,并發(fā)歡迎信息給客戶; 客戶接收服務(wù)器發(fā)送的信息并顯示;TCP套接字例程 下面我們考慮在以下三種異常情況發(fā)生后,tcp客戶服務(wù)器程序的反
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024-2025學(xué)年高中政治課時分層作業(yè)8英法兩國政體的異同含解析新人教版選修3
- 2024年新教材高中生物56主題歸納能力培優(yōu)含解析新人教版必修2
- 2024年中考物理母題題源系列專題19電磁感應(yīng)磁吃電流的作用
- 電子通信協(xié)議的跨平臺兼容性研究
- 電子商務(wù)平臺公開戶的用戶體驗優(yōu)化方案
- 員工轉(zhuǎn)證申請書
- 民間借貸金融創(chuàng)新業(yè)務(wù)合作合同(2025版)
- 戶口遷移申請書范文7篇
- 二零二五年度新能源汽車臨時司機(jī)聘用協(xié)議書
- 退話劇社申請書
- 植物之歌觀后感
- 空氣能熱泵安裝示意圖
- 建筑工程施工質(zhì)量驗收規(guī)范檢驗批填寫全套表格示范填寫與說明
- 2020年中秋國慶假日文化旅游市場安全生產(chǎn)檢查表
- 人教版高中數(shù)學(xué)選擇性必修二導(dǎo)學(xué)案
- 昆明天大礦業(yè)有限公司尋甸縣金源磷礦老廠箐-小凹子礦段(擬設(shè))采礦權(quán)出讓收益評估報告
- 心有榜樣行有力量 -從冬奧冠軍徐夢桃身上感受青春奮斗初中主題班會
- GB/T 3860-1995文獻(xiàn)敘詞標(biāo)引規(guī)則
- 七年級英語下冊閱讀理解10篇
- 設(shè)計質(zhì)量、進(jìn)度保證措施
- 醫(yī)院評審工作臨床科室資料盒目錄(15個盒子)
評論
0/150
提交評論