unix網絡編程 套接字


第三章 套接字編程簡介

大多數套接字函數都需要一個指向套接字地址結構的指針作為參數。每個協議族都定義了它的套接字地址結構。這些結構的名字均已sockaddr_開頭,並以對應的唯一后綴結束。

1.套接字地址結構

IPv4套接字結構

IPv4套接字地址結構通常稱為“網際套接字地址結構”,它以sockaddr_in命名,定義在<netinnet/in.h>頭文件中。

以下是網際(IPv4)套接字地址結構:sockaddr_in

struct in_addr; { int_addr_t s_addr; /*32位IPv4的地址*/ /*網絡字節命令*/ }; struct sockaddr_in { uint8_t sin_len; sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; char sin_zero[8]; }; 

長度字段sin_len是為了增加對OSI協議的支持而隨4.3BSD-Reno添加到。(因為有了長度字段,才簡化了長度可以變套接字地址結構的處理)

POIX規范只需要這個結構中的3個字段:sin_family、sin_add、sin_port。對於符合POIX的實現來說,定義額外的結構字段是可以接收的,這對於網際套接字地址結構來說也是正常的。幾乎所有的實現都增加了sin_zero字段,所以所有的套接字地址結構大小都至少是16字節。

數據類型 說明 頭文件
int8_t 帶符號的8位整數 <sys/typcs.h>
uint8_t 無符號的8位整數 <sys/typcs.h>
int16_t 帶符號的16位整數 <sys/typcs.h>
uint16_t 無符號的16位整數 <sys/typcs.h>
int32_t 帶符號的32位整數 <sys/typcs.h>
uint32_t 無符號的32位整數 <sys/typcs.h>
sa_family_t 套接字地址結構的地址族 <sys/socket.h>
socklen_t 套接字地址結構的長度,一般為uint32_t <sys/socket.h>
in_addr_t

IPv4地址,一般為unit32_t

<netine/in.h>
in_port_t TCP或UDP端口,一般為uint16_t <netine/in.h>

(擴展)POSIX(Portable Operating System Interface,可移植操作系統接口)

POIX是接口。

POSIX標准定義了操作系統應該為應用程序提供的接口標准,是IEEE為要在各種UNIX操作系統上運行的軟件而定義的一系列API標准的總稱,其正式稱呼為IEEE 1003,而國際標准名稱為ISO/IEC 9945。

(一些常見的縮寫)

addr(address,地址)

info(information,信息)

通用套接字地址結構

通用套接字地址結構:sockaddr

struct sockaddr { uint8_t sa_len; sa_family_t sa_family; char sa_data[14]; };

IPv6套接字地址結構

IPv6套接字地址結構在<netinet/in.h>頭文件中定義

struct in6_addr { unit8_t s6_add[16]; }; #define SIN6_LEN struct sockaddr_in6 { uint8_t sin6_len; sa_family_t sin6_family; in_port_t sin6_port; uint32_t sin6_flowinfo; struct in6_addr sin6_addr; uint32_t sin6_scope_id; }; 

新的通用套接字地址結構

新的struct sockaddr_storage足以容納系統所支持的任何套接字地址結構。sockaddr_storage結構在<netinet/in.h>頭文件中定義

struct sockaddr_storage { uint8_t ss_len; sa_family_t ss_family; };

不同套接字地址結構的比較

2.值-結果參數

傳遞方式取決於該結構的傳遞方向:是從進程到內核,還是從內核到進程、

1)從進程到內核傳遞套接字地址結構的函數有3個:bind,connect和sendto

這些函數的一個參數時指向某個套接字地址結構的指針,另一個參數時該結構的整數大小。

!!套接字地址結構大小的數據類型是socklen_t。(POIX建議將socklen_t定義為uint32_t)

2)從內核到進程傳遞套接字地址結構的函數有4個:accept,recvfrom,getsocknamo和getpeername。

這4個函數的其中兩個參數是指向某個套接字地址結構的指針和指向表示該結構大小的整數變量的指針。

值-結果參數:把套接字地址結構大小這個參數從一個整數改為指向某個整數變量的指針,其原因在於,當函數被調用時,結構大小是一個值,它告訴內核該結構的大小,這樣內核在寫該結構時不至於越界;

當函數返回時,結構大小又是一個結果,它告訴進程內核在該結構中究竟儲存了多少信息。

3.字節排序函數

小端和大端(內存中存儲兩個字節有兩種方法)

小端(little-endian):將低序字節存儲在起始地址

大端(big-endian):將高序字節存儲在起始地址

主機字節序:某個給定系統所用的字節序

輸出字節序的程序:

#iclude"unp.h" int main(int argc,char **argv) { union{ short s; char c[sizeof(short)]; }un; un.s=0x0102; printf("%s:",CUP_VENDOR_OS); if(sizeof(short)==2){ if(un.c[0]==1&&un.c[1]==2) printf("big-endian\n"); else if (un.c[0]==2&&un.c[1]==1) printf("little-endian\n"); else printf("unknown\n"); }else printf("sizeof(short)=%d\n",sizeof(short)); exit(0); } 

4.字節操縱函數

bzero:bzero把目標字節串指定數目的字節置為0。我們常用該函數把一個套接字地址結構初始化為0.

bocpy:指定數目的字節從源字節串移動到目標字節串。

bcmp:比較兩個任意的字節串,若相同返回值為0,否則返回值為非0.

memset:把目標字節串指定數目的字節置為c。

mencmp:比較兩個任意的字符串,若相同為0,否則返回一個非0值,是大於0還是小於0則取決於第一個不等的字節。

5.inet_aton、net_addr和inet_ntoa函數(地址轉換函數)

6.inet_pton和inet_ntop函數

函數中的p代表表達(presentation),n代表數值(numeric)

地址的表達格式通常是ASCII字符串,數值格式則是存放到套接字地址結構中的二進制。

1)只支持IPv4的inet_pton函數的簡單定義

int inet_pton(int family,const char *strptr,void *addrptr) { if(family==AF_INET) { struct in_addr in_val; if(inet_aton(strptr,&in_val)) { memcpy(addrptr,&in_val,sizeof(struct int_addr)); return(1); } return(0); } errno=EAFNOSUPPROT; return(-1); }

2)只支持IPv4的inet_ntop函數的簡化版本

const char* inet_ntop(int family,const void *addrptr,char *strptr,size_t len) { const u_char *p=(const u_char *)addrptr; if(family==AF_INET) {char temp[INET_ADDRSTRLEN]; snprintf(temp,sizeof(temp),"%d,%d,%d,%d",p[0],p[1],p[2],p[3]); if(strlen(temp)>=len) { errno=ENOSPC; return (NULL); } strcpy(strptr,temp); return (strptr); } errno =EAFNOSUPPORT; return (NULL); } 

 

7.sock_ntop和相關函數

作用:它以指向某個套接字地址結構的指針為參數,查看該結構的內部,然后調用適當的函數返回該地址的表達格式。

#include"unp.h" char *sock_ntop(const struct sockaddr *sockaddr,socklen_t addrlen); //若成功則為非空指針,若出錯為NULL

!!sock是什么?很多時候我們在寫代碼為了表達清楚這個元素背后的意思,我們都會采用英文單詞的縮寫。例如這個sock是套接字的英文(socket)的縮寫。然后我們可以結合它的意思來理解這些元素的意義,例如sockaddr指的是套接字的套接字的地址,socklen指的是套接字的長度。雖然看到一大串英文字母感到賊煩,但是很多只要理解意思之后就沒有那么可怕了。嘻嘻。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM