互聯(lián)網(wǎng)絡(luò)程序設(shè)計(jì)第2章.ppt
《互聯(lián)網(wǎng)絡(luò)程序設(shè)計(jì)第2章.ppt》由會員分享,可在線閱讀,更多相關(guān)《互聯(lián)網(wǎng)絡(luò)程序設(shè)計(jì)第2章.ppt(38頁珍藏版)》請?jiān)谘b配圖網(wǎng)上搜索。
1、第二章、套接口編程基礎(chǔ),套接口基本概念 套接口地址結(jié)構(gòu) 字節(jié)序 網(wǎng)絡(luò)編程基本模型 一些常用函數(shù),概述,本章主要介紹網(wǎng)絡(luò)編程的基本數(shù)據(jù)結(jié)構(gòu)、字節(jié)序、網(wǎng)絡(luò)編程的基本模型 由于課時限制,Socket API的基本編程函數(shù)不集中講述,將在本章和下一章中結(jié)合基本概念和編程講述 下一章,將結(jié)合簡單的迭代服務(wù)器講述套接口的基本函數(shù),1. 套接字概念,Unix、TCP/IP協(xié)議的發(fā)展 Unix與BSD TCP/IP協(xié)議的實(shí)現(xiàn) 以BSD為基礎(chǔ)的協(xié)議編程接口socket API成為網(wǎng)絡(luò)編程的標(biāo)準(zhǔn) 4.4BSD的協(xié)議棧中實(shí)現(xiàn)中了4種協(xié)議,不僅僅是TCP/IP TCP/IP XNS(已經(jīng)刪除) OSI/TLI Uni
2、x域,,BSD協(xié)議棧結(jié)構(gòu) Socket API是一個網(wǎng)絡(luò)編程接口,并非一個協(xié)議層 套接口除了操縱傳輸層外、還可以操縱網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層 Socket API可以操縱多種協(xié)議棧:TCP/IP、Unix、TLI、XNS等,,協(xié)議棧的實(shí)現(xiàn) 參考Richard. Stevens, TCP/IP詳解卷2 Linux下的實(shí)現(xiàn)在/usr/src/linux-source-2.6.32/net,創(chuàng)建套接字的函數(shù)socket,要使用網(wǎng)絡(luò)協(xié)議,首先要創(chuàng)建套接口(socket) man socket,,什么是套接口? socket是一個文件描述符 BSD的實(shí)現(xiàn)者,將網(wǎng)絡(luò)協(xié)議的操作抽象成為文件的操作 為什么要如此抽象
3、?文件的讀、寫等操作具有一般性 除了socket抽象成為文件外,還有那些東西被抽象成為文件? 目錄 設(shè)備 epoll、kqueue,,文件描述符的含義 進(jìn)程結(jié)構(gòu) 文件描述符表 文件表 文件結(jié)構(gòu) socket結(jié)構(gòu) 文件操作函數(shù)表 inpcb,,,,套接字類型,套接字支持多種通信協(xié)議: Unix:Unix系統(tǒng)內(nèi)部協(xié)議 INET:IP版本4 INET6:IP版本6 套接字類型,即應(yīng)用程序希望的通信服務(wù)類型 SOCKET_STREAM:雙向可靠數(shù)據(jù)流,對應(yīng)TCP SOCKET_DGRAM:雙向不可靠數(shù)據(jù)報(bào),對應(yīng)UDP SOCKET_RAW:是低于傳輸層的低級協(xié)議或物理網(wǎng)絡(luò)提供的套接字類型,可以訪問內(nèi)部
4、網(wǎng)絡(luò)接口。 Protocol? /usr/include/bits/socket.h /usr/include/netinet/in.h,2. 網(wǎng)絡(luò)地址結(jié)構(gòu),網(wǎng)絡(luò)的地址表示方式有哪些?IPv4 域名,Dns 點(diǎn)分十進(jìn)制,192.168.1.1 編程使用的結(jié)構(gòu) IPv4地址定義: /usr/include/netinet/in.h /usr/include/bits/sockaddr.h /* Internet address. */ typedef uint32_t in_addr_t; struct in_addr in_addr_t s_addr; ;,,#define __SOCKAD
5、DR_COMMON(sa_prefix) sa_family_t sa_prefix##family/* sockaddr.h */ /* Structure describing an Internet socket address. */ struct sockaddr_in __SOCKADDR_COMMON (sin_); /* Socket family */ in_port_t sin_port;/* Port number. */ struct in_addr sin_addr;/* Internet address. */ /* Pad to size of struct s
6、ockaddr. 8bytes*/ unsigned char sin_zerosizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE - sizeof (in_port_t) - sizeof (struct in_addr); ;/* 16bytes */,,Linux中的sockaddr_in定義與教材中稍有不同 注意如下幾個宏: /* Address to accept any incoming messages. */ #defineINADDR_ANY((in_addr_t) 0 x00000000) /* Address to sen
7、d to all hosts. */ #defineINADDR_BROADCAST((in_addr_t) 0 xffffffff) /* Address indicating an error return. */ #defineINADDR_NONE((in_addr_t) 0 xffffffff),,IPv6地址定義 /* Ditto, for IPv6. */ struct sockaddr_in6 __SOCKADDR_COMMON (sin6_); in_port_t sin6_port; /* Transport layer port # */ uint32_t sin6_
8、flowinfo; /* IPv6 flow information */ struct in6_addr sin6_addr; /* IPv6 address */ uint32_t sin6_scope_id;/* IPv6 scope-id */ ;/* 28bytes */,,通用套接字地址結(jié)構(gòu)(/usr/include/bits/socket.h) /* Structure describing a generic socket address. */ struct sockaddr __SOCKADDR_COMMON (sa_); /* Common data: address
9、family and length. */ char sa_data14;/* Address data. */ ; 與教材中定義稍有不同 使用sockaddr_in結(jié)構(gòu)前,一定要清空它 bzero(,,,3. 字節(jié)序,什么是字節(jié)序?(網(wǎng)絡(luò)地址使用的一個細(xì)節(jié)問題) 字節(jié)作為存儲和尋址的最小單位 以字節(jié)為單位在內(nèi)存中的排列問題 不同類型的機(jī)器上,對c語言原生類型字節(jié)排列的順序可能不一樣 例子 union short s; char csizeof(short); un; un.s = 0 x0201; printf(“%d, %dn”, un.c0, un.c1); x86運(yùn)行結(jié)果:1, 2 p
10、owerpc運(yùn)行結(jié)果:2, 1,02,01,01,02,,,地址低位,地址高位,x86,powerpc,un.c0,un.c1,,將小序號字節(jié)放在低位字節(jié)的機(jī)器,稱為小序機(jī)器;將大序號字節(jié)放在高位字節(jié)的機(jī)器,稱為大序機(jī)器 x86是小序機(jī)器,Arm是大序機(jī)器 網(wǎng)絡(luò)字節(jié)序,按照大序機(jī)器傳送的字節(jié)序,02,01,,02,01,02,01,powerpc,x86,解釋?,,字節(jié)變換函數(shù)(/usr/include/netinet/in.h) htons ntohs htonl ntohl,字節(jié)序的理解,一個字符串在大序和小序機(jī)器上的排列是否有不同? 一個字節(jié)0 x12從大序機(jī)器傳遞到小序機(jī)器上,是否表現(xiàn)
11、為0 x21? C語言中的bit位定義,例如TCP頭部的定義: # if __BYTE_ORDER == __LITTLE_ENDIAN u_int16_t res1:4; u_int16_t doff:4; # elif __BYTE_ORDER == __BIG_ENDIAN u_int16_t doff:4; u_int16_t res1:4; ,,注意只有C語言的原生類型:char、short、long等,才會出現(xiàn)字節(jié)序問題。下例結(jié)構(gòu)中,x、y是否會出現(xiàn)位置顛倒的情況? struct X struct Y y; struct Z z; ; 網(wǎng)絡(luò)地址192.168.1.1,在
12、IP包中的排列如何?,4.網(wǎng)絡(luò)編程基本模型,在面向連接的網(wǎng)絡(luò)協(xié)議編程時,通常都會采用client/sever模型,這是由協(xié)議所決定的。 并且是多對一的服務(wù),,對等網(wǎng)(Peer-to-Peer,P2P)呢? P2P是指邏輯上對等,如果采用TCP通信,在一次通信中,仍然存在client/server的劃分 UDP呢? socket bind recvfrom sendto,采用同一個端口?,5. 常用函數(shù),字節(jié)操縱函數(shù) /usr/include/strings.h #include void bzero(void *dest, size_t nbytes); void bcopy(const vo
13、id *src, void *dest, size_t nbytes); int bcmp(const void *ptr1, const void *ptr2, size_t nbytes); Returns: 0 if equal, nonzero if unequal /usr/include/string.h #include void *memset(void *dest, int c, size_t len); void *memcpy(void *dest, const void *src, size_t nbytes); int memcmp(const void *ptr1,
14、 const void *ptr2, size_t nbytes); Returns: 0 if equal, 0 if unequal (see text),,地址變換函數(shù) /usr/include/arpa/inet.h #include int inet_pton(int family, const char *strptr, void *addrptr); Returns: 1 if OK, 0 if input not a valid presentation format, -1 on errorconst char *inet_ntop(int family, const v
15、oid *addrptr, char *strptr, size_t len); Returns: pointer to result if OK, NULL on error,inet_pton,10 int 11 inet_pton(int family, const char *strptr, void *addrptr) 12 if (family == AF_INET) struct in_addr in_val; if (inet_aton(strptr, ,例子,char IPdotdec20; //存放點(diǎn)分十進(jìn)制IP地址struct in_addr s; // IPv4地
16、址結(jié)構(gòu)體int main (void) // 輸入IP地址 printf(Please input IP address: ); scanf(%s, ,,錯誤處理函數(shù) errno /usr/include/errno.h #ifndef errno extern int errno; #endif 當(dāng)系統(tǒng)調(diào)用或者庫調(diào)用出錯時,errno給出出錯的信息 注意,errno并不是系統(tǒng)調(diào)用或函數(shù)調(diào)用的返回值 errno可以看成一個整數(shù)值,出錯時errno為非0值 errno是每線程一個實(shí)例 if (somecall() == -1) printf(somecall() failedn); if (er
17、rno == ...) ... ,,perror #include void perror(const char *s); perror打印errno對應(yīng)的出錯信息,同時打印一個定制的字符串s perror定制的能力有限 strerror #include char *strerror(int errnum); strerror打印errnum對應(yīng)的出錯信息,,讀寫函數(shù) 一個文件描述符對應(yīng)的操作封裝在file_operations結(jié)構(gòu)中, /usr/src/linux-source../include/linux/sched.h struct task_struct /* open file
18、 information */ struct files_struct *files; ; /usr/src/linux-source../include/linux/fdtable.h struct files_struct struct fdtable *fdt; ;,,struct fdtable struct file ** fd; /* current fd array */ ; /usr/src/linux-source../include/linux/fs.h struct file const struct file_operations*f_op; ;,,struct
19、 file_operations ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*aio_write) (struct kiocb *, const struct iovec *,
20、unsigned long, loff_t); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); ;,,read/write函數(shù)調(diào)用與socket關(guān)聯(lián)的file_operations結(jié)構(gòu)中操作函數(shù),向外收發(fā)數(shù)據(jù) 對應(yīng)于BSD的協(xié)議棧,write最終要調(diào)用sosend sosend函數(shù)會調(diào)用協(xié)議的pr_usrreq函數(shù) read要調(diào)用soreceive函數(shù) soreceive函數(shù)會調(diào)用協(xié)議的pr_usrreq函數(shù) pr_usrreq是每個協(xié)議需要實(shí)現(xiàn)的用戶對協(xié)議的操作函數(shù)。除了收發(fā)數(shù)據(jù)最終會調(diào)用p
21、r_usrreq外,bind、connet等函數(shù),由于會對TCP協(xié)議進(jìn)行操縱,也會調(diào)用pr_usrreq。 pr_usrreq在哪里?在一個稱為protosw結(jié)構(gòu)中定義為一個函數(shù)插槽,,協(xié)議的堆疊,TCP/IP詳解卷2第7章,read函數(shù),#include ssize_t read(int fd, void *buf, size_t count); 返回值:=0正確返回;==-1, 出錯 count表示buf的大小,返回值無論如何不會超過它的大小 有兩種返回0的情況 對端關(guān)聯(lián)TCP連接,讀到頭了; count = 0 返回-1,需要檢查errno,有些錯誤可以處理 EAGAIN/EWOULDB
22、LOCK,表示非阻塞的讀寫 EINTR,讀阻塞被信號中斷,,#include ssize_t write(int fd, const void *buf, size_t count); 返回值:0,實(shí)際發(fā)送的數(shù)據(jù)個數(shù);==-1,出錯 向?qū)Χ税l(fā)送數(shù)據(jù),count表示buf中所含數(shù)據(jù)的大小 出錯的情況 EINTR,被信號中斷 EAGAIN,非阻塞發(fā)送 EPIPE,表示socket另一端寫關(guān)閉,何種情況?,數(shù)據(jù)傳輸函數(shù)send,#include #include ssize_t send (int s, const void *msg, size_t len, int flags); 返回:非0發(fā)送
23、成功的數(shù)據(jù)長度;-1出錯; flags 是傳輸控制標(biāo)志,其值定義如下: 0:常規(guī)操作,如同write()函數(shù) MSG_OOB,發(fā)送帶外數(shù)據(jù)。 MSG_DONTROUTE:忽略底層協(xié)議的路由設(shè)置,只能將數(shù)據(jù)發(fā)送給與發(fā)送機(jī)處在同一個網(wǎng)絡(luò)中的機(jī)器上。,數(shù)據(jù)傳輸函數(shù)recv,#include #include ssize_t recv(int s, void *buf ,size_t len, int flags); 返回:大于0表示成功接收的數(shù)據(jù)長度;0: 對方已關(guān)閉,-1:出錯。 flags是傳輸控制標(biāo)志,其值定義如下: 0:常規(guī)操作,如同read()函數(shù); MSG_PEEK:只查看數(shù)據(jù)而不讀出數(shù)據(jù),后續(xù)讀操作仍然能讀該數(shù)據(jù); MSG_OOB:忽略常規(guī)數(shù)據(jù),而只讀帶外數(shù)據(jù); MSG_WAITALL:recv函數(shù)只有在將接收緩沖區(qū)填滿后才返回。,思考題,使用C++封裝IPv4和IPv6地址。提示:參考boost::asio庫、ACE庫。 UDP是否可以采用read、write函數(shù)發(fā)送數(shù)據(jù)?應(yīng)該如何做到?為什么UDP通常采用recvfrom/sendto來收發(fā)數(shù)據(jù)?,
- 溫馨提示:
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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 6.煤礦安全生產(chǎn)科普知識競賽題含答案
- 2.煤礦爆破工技能鑒定試題含答案
- 3.爆破工培訓(xùn)考試試題含答案
- 2.煤礦安全監(jiān)察人員模擬考試題庫試卷含答案
- 3.金屬非金屬礦山安全管理人員(地下礦山)安全生產(chǎn)模擬考試題庫試卷含答案
- 4.煤礦特種作業(yè)人員井下電鉗工模擬考試題庫試卷含答案
- 1 煤礦安全生產(chǎn)及管理知識測試題庫及答案
- 2 各種煤礦安全考試試題含答案
- 1 煤礦安全檢查考試題
- 1 井下放炮員練習(xí)題含答案
- 2煤礦安全監(jiān)測工種技術(shù)比武題庫含解析
- 1 礦山應(yīng)急救援安全知識競賽試題
- 1 礦井泵工考試練習(xí)題含答案
- 2煤礦爆破工考試復(fù)習(xí)題含答案
- 1 各種煤礦安全考試試題含答案