unix網絡編程-第3,4章套接字編程

第3章 套接字編程簡介

1.套接字的基本結構

數據定義:

struct sockaddr {

unsigned short sa_family; /* address族, AF_xxx */

char sa_data[14]; /* 14 bytes的協議地址 */

};

sa_family 一般來說,都是“AFINET”。

sa_data 包含了一些遠程電腦的地址、端口和套接字的數目,它裏面的數據是雜溶在一

切的。

爲了處理struct sockaddr, 程序員建立了另外一個相似的結構 struct sockaddr_in:

struct sockaddr_in (“in” 代表 “Internet”)

struct sockaddr_in {

short int sin_family; /* Internet地址族 */

unsigned short int sin_port; /* 端口號 */

struct in_addr sin_addr; /* Internet地址 */

unsigned char sin_zero[8]; /* 添0(和struct sockaddr一樣大小)*/

};

這個結構提供了方便的手段來訪問socket address(struct sockaddr)結構中的每一個元

2.套接字字節轉換程序的列表:

計算機內存中有兩種數據存儲方式,一種爲小端字節序,也就是低地址存儲數據低字節,高地址存儲數據高字節;一種爲大端字節序,也就是低地址存儲高字節,高地址存儲低字節。網絡字節序採用大端字節序,而主機字節序有可能爲小端字節序,因此,存在着字節序的轉換問題。

l htons()——“Host to Network Short”主機字節順序轉換爲網絡字節順序(對無符號

短型進行操作4 bytes)

l htonl()——“Host to Network Long” 主機字節順序轉換爲網絡字節順序(對無符

號長型進行操作8 bytes)

l ntohs()——“Network to Host Short “ 網絡字節順序轉換爲主機字節順序(對無符

號短型進行操作4 bytes)

l ntohl()——“Network to Host Long “ 網絡字節順序轉換爲主機字節順序(對無符

號長型進行操作8 bytes)

3. IP 地址轉換

in_addr_t inet_addr(const char *straddr);

  int inet_aton(const char* straddr,struct in_addr *addrp);

  char* inet_ntoa(struct in_addr inaddr);

頭文件:sys/socket.h netinet/in.h arpa/inet.h

inet_addr成功返回32位網絡字節序地址,出錯返回INADDR_NONE。INADDR_NONE爲linux定義的一個常數,是一個不存在的ip地址;

inet_aton將ASCII轉換成網絡字節序的32位二進制值,輸入的ASCII放在straddr中,轉換後放在addrp中,成功返回1,失敗返回0;

inet_ntoa將32位二進制地址轉換成ASCII地址,成功返回ASCII值,失敗返回NULL。

Linux 系統提供和很多用於轉換IP 地址的函數.首先,假設你有一個struct sockaddr_in ina,並且你的IP 是166.111.69.52 ,你想把你的IP 存儲到ina 中。你可以使用的函數: inet_addr() ,它能夠把一個用數字和點表

示IP 地址的字符串轉換成一個無符號長整型。你可以像下面這樣使用它:

ina.sin_addr.s_addr = inet_addr(“166.111.69.52”);

注意:

l inet_addr() 返回的地址已經是網絡字節順序了,你沒有必要再去調用htonl() 函數

反過來,如果你有一個struct in_addr 並且你想把它代表的IP 地址打印出來(按照數字.數字.數字.數字的格式),那麼你可以使用函數inet_ntoa()(“ntoa”代表“Network to ASCII”),它會把struct in_addr 裏面存儲的網絡地址以數字.數字.數字.數字的格式。

l inet_ntoa() 使用struct in_addr 作爲一個參數,不是一個長整型值。

4.字節操作函數   

字節操作函數主要是用於讀取結構體中的某幾個字節。

    void bzero(void *dest,size_t nbytes);

    void bcopy(const void *src,void *dest,size_t nbytes);

    int bcmp(const void *prt1,const void *ptr2,size_t nbytes);

    void *memset(void *dest,int c,size_t len);

    void *memcpy(void *dest,const void *src,size_t nbytes);

    int memcmp(const void *ptr1,const void ptr2,size_t nbytes);

頭文件:string.h

說明:以b打頭的函數爲支持套接口函數的系統所提供,mem爲支持ANSI C庫提供的函數;其中,bzero將制定的起始地址設置爲0(nbytes表示字長),bcopy和memcpy爲複製,bcmp和memcmp爲比較,memset將目標中指定數據的字節設置爲指定的值。


5.readn,writen和readline函數


第4章 基於TCP套接字編程

基本TCP客戶-服務器程序的套接口函數如下圖:

1、socket函數

原型:#include<sys/socket.h>

int socket(int family, int type, int protocol); 返回值:非負描述符--成功, -1--出錯;

作用:指定期望的通信協議接口(TCP或UDP或unix域字節協議等)

family 指明協議簇

解釋
AF_INET IPv4協議
AF_INET6 IPv6協議
AF_LOCAL Unix與協議
AF_ROUTE 路由套接口
AF_KEY 密鑰套接口
type類型

類型 解釋
SOCK_STREAM 字節流套接口
SOCK_DGRAM 數據包套接口
SOCK_RAW 原始套接口

protocol參數應設置爲某個協議類型常值,或者設爲0.

protocol 說明
IPPROTO_TCP TCP傳輸協議
IPPROTO_UDP UDP傳輸協議
IPPROTO_SCTP SCTP傳輸協議

2、connect函數

原型:#include<sys/socket.h>

int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);返回值:0---成功,-1----出錯;

作用:客戶端用connect 函數建立一個與TCP服務器的連接;

參數:sockfd,套接口描述字;

             servaddr,套接口地址結構的指針,該地址結構需要包含服務器IP地址和端口號;

             addrlen, 套接口地址結構的大小;

關於connect出錯返回的幾種情況:

  •  如果TCP客戶端沒有收到SYN分節的響應,則返回ETIMEDOUT。
  • 如果對客戶的SYN的響應是RST,則表明該服務器主機在我們指定的端口上沒有進程在等待與之連接,這稱之爲硬錯,客戶端接到RST,立即返回錯誤ECONNREFUSED;
  • 如果某客戶端發出的SYN在中間的路由器上引發了一個目的地不可達的ICMP錯誤,這稱之爲軟錯,客戶端按時間間隔繼續發送SYN,在規定時間仍未收到響應,則返回EHOSTUNREACH;
3、bind函數

原型:#include<sys/socket.h>

int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);返回值:0---成功,-1----出錯;

作用:給套接口分配一個本地協議地址;

參數:sockfd,套接口描述字;
    myaddr,特定於協議的地址結構的指針,對於TCP,可以指定一個IP地址,一個端口號;
           addrlen,第二個參數地址結構的長度;


4、listen函數

原型:#include<sys/socket.h>

int listen(int sockfd, int backlog);  返回值:0---成功,-1---出錯;

作用 : 將未連接的套接口轉換成被動套接口,指示內核應接受此套接口的連接請求;第二個參數規定了次套接口排隊的最大連接數;

參數:sockfd,套接口描述字;

           backlog,套接口排隊的最大連接數;

對與第二個參數backlog的理解:

  • 未完成連接隊列,爲每個已由客戶端發出併到達服務器,服務器正在等待完成相應TCP三路握手過程的SYN分節開設一個條目,這些套接口都處於SYN_RCVD;
  • 已完成隊列:爲每個已完成TCP三路握手過程的客戶開設一個條目,這些套接口都處於ESTABLISHED狀態;
關係如下圖:

5、accept函數
原型:#include<sys/socket.h>
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);返回值:非負描述符---成功,-1----出錯;
作用:有服務器調用,從已完成連接隊列頭返回下一個已完成連接,若已完成連接隊列爲空,則進程睡眠。
參數:sockfd,套接口描述字;
    cliaddr,客戶進程協議地址;
   addrlen,第二個參數,客戶進程協議地址的長度;

6、close函數
原型:#include<unistd.h>
int close(int sockfd);
作用:將套接口坐上“已關閉”標記,並立即返回到進程;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章