IP地址的作用是標示計算機的網卡地址,每臺計算機都有一個IP地址;端口,是指計算機中為了標示在計算機中訪問網絡的不同程序而設的編號,并不是網卡接線的端口,而是不同程序的邏輯編號,并不是實際存在的;域名,是用來代替IP地址來標示計算機的一種直觀名稱,例如百度網站的IP地址是202.108.22.43,這個IP地址沒有任何邏輯含義,不便記憶,而www.baidu.com是一個便于記憶的名稱,用于代替這個IP地址;套接字的本意是插座,在網絡中用來描述計算機中不同程序與其他計算機程序的通信方式。
常用的套接字類型有3種:
(1)流套接字(SOCK——STREAM):使用了面向連接的可靠的數據通信方式,即TCP協議;
(2)數據報套接字(Raw Sockets):使用了不面向連接的數據傳輸方式,即UDP;
(3)原始套接字(SOCK——RAW):沒有經過處理的IP數據包,可以根據自己程序的要求進行封裝。
網絡協議是指不同的計算機、不同的操作系統在進行網絡通信時的統一約定。網絡服務指的是網絡上的計算機通過運行程序為其他的計算機提供信息或運算的功能。
套接字相關的數據類型:sockaddr和sockaddr_in;sockaddr用來保存一個套接字,定義如下:
struct sockaddr
{
unsigned short int sa_family; //指定通信地址類型,如果是TCP/IP通信,則值為AF_inet
char sa_data[14]; //最多用14個字符長度,用來保存IP地址和端口信息
};
sockaddr_in的功能與socdaddr相同,也是用來保存一個套接字的信息,不同的是將IP地址與端口分開為不同的成員,定義如下:
struct sockaddr_in
{
unsigned short int sin_family; //指定通信地址類型
uint16_t sin_port; //套接字使用的端口號
struct in_addr sin_addr; //需要訪問的IP地址
unsigned char sin_zero[8]; //未使用的字段,填充為0
};
在這一結構中,in_addr也是一個結構體,定義如下,用于保存一個IP地址:
struct in_addr
{
uint32_t s_addt;
};
用域名取得主機的IP地址:
struct hostent *gethostbyname(const char *name);
結構體hostent的定義如下:
struct hostent
{
char *h_name;//正式的主機名稱
char **h_aliases;//這個主機的別名
int h_addrtype;//主機名的類型
int h_length;//地址的長度
char **h_addr_list;//從域名服務器取得的主機地址
};
用IP地址返回域名:
struct hostent *gethostbyaddr(const void *addr,socklen_t len,int type);
由協議名取的協議數據:
struct protoent *getprotobyname(char *name);
結構體protoent定義如下:
struct protoent
{
char *p_name;//協議的名稱
char **p_aliases;//協議的別名
int p_proto;//協議的序號
};
由協議編號取得協議信息:
struct protoent *getprotobynumber(int proto);
取得系統支持的所有協議:
struct protoent *getprotoent(void);
取得系統支持的網絡服務:
struct servent *getservent(void);
結構體servent定義如下:
struct servent
{
char *s_name;//這個服務的名稱
char **s_aliases;//這個服務可能的別名
int s_port;//這個服務可能的端口
char *s_proto;//這個服務可能使用的協議
};
用名稱取得系統所支持的服務:
struct servent *getservbyname(char *name,char *proto); //name:服務器名稱,proto服務器所使用的協議;
由端口取得服務名稱:
struct servent *getservbyport(int port,char *proto)
//port是端口的編號,需要注意的是這個端口號需要用htons()函數進行轉換,proto表示一個協議的字符串;
將網絡地址轉換成長整型:
long inet_addr(char *cp); //cp表示一個IP地址字符串;
將長整型IP地址轉換成網絡地址即大小端模式轉換:
char *inet_ntoa(struct in_addr in);
將計算機中的32位長整型數轉換成網絡字符順序的32位長整型數:
uint32_t htonl(uint32_t hostlong);
將計算機中的16位整型數轉換成網絡字符順序的16位整型數:
uint16_t htons(uint16_t hostshort);
將網絡字符順序的32位長整型數轉換成計算機中的32位長整型數:
uint32_t ntohl(uint32_t netlong);
將網絡字符順序的16位整型數轉換成計算機中的16位整型數:
uint16_t ntohs(uint16_t netshort);
herror函數顯示錯誤:
void herror(const char *S); //s是一個字符串,函數先輸出這個字符串,然后輸出錯誤信息
創建套接字函數:
int socket(int domain,int type,int protocol);
//參數domain用于指定創建套接字所使用的協議族(可取AF_UNIX,AF_INET,AF_INTE6)
//參數type指定套接字的類型(可取SOCK_STREAM,SOCK_DGRAM,SOCK_RAW)
//參數protocol通常設置為0
在指定套接字上創建鏈接函數:
int connect(int sockfd,const struct sockaddr *serv_addr,socklen_t addrlen);
//參數sockfd是一個由函數socket創建的套接字
//參數serv_addr是一個地址結構,指定服務器的IP地址和端口號
//參數addrlen為參數serv_addr的長度
將一個套接字和某個端口綁定在一起的函數:
int bind(int sockfd,struct sockaddr *my_addr,socklen_t addrlen);
//一般只有服務器端的程序調用,參數my_addr指定了sockfd將綁定到的本地地址,可以將參數my_addr的sin_addr設置為INADDR_ANY而不是某個確定IP地址就可以綁定到任何網絡接口。
把套接字轉化為被動監聽函數:
int listen(int s,int backlog);
//參數s為套接字,參數backlog指定鏈接請求隊列的最大長度;
接收連接請求函數:
int accept(int s,struct sockaddr *addr,socklen_t *addrlen);
//參數s是由函數socket創建,經函數bind綁定到本地某一端口上,然后通過函數listen轉化而來的監聽套接字
//參數addr用來保存發起連接請求的主機的地址和端口
//參數addrlen是addr所指向的結構體的大小
在TCP套接字上發送數據函數:
ssize_t send(int s,const void *msg,size_t len,int flags);
//函數只能對處于連接狀態的套接字使用,參數s為已建立好連接的套接字描述符,即accept函數的返回值
//參數msg指向存放待發送數據的緩沖區
//參數len為待發送數據的長度,參數flags為控制選項,一般設置為0
在TCP套接字上接收數據函數:
ssize_t recv(int s,void *buf,size_t len,int flags);
//函數recv從參數s所指定的套接字描述符(必須是面向連接的套接字)上接收數據并保存到參數buf所指定的緩沖區
//參數len則為緩沖區長度,參數flags為控制選項,一般設置為0
在UCP套接字上發送數據函數:
ssize_t sendto(int s,const void *msg,size_t len,int flags,const struct sockaddr *to,socklen_t tolen);
//函數功能與函數send類似,但函數sendto不需要套接字處于連接狀態,所以該函數通常用來發送UDP數據,同時因為是無連接的套接字,在使用sendto時需要指定數據的目的地址,參數msg指向待發送數據的緩沖區。
//參數len指定了待發送數據的長度
//參數flags是控制選項,含義與send函數中的一致
//參數to用于指定目的地址,目的地址的長度由tolen指定
在UDP套接字上接收數據函數:
ssize_t recvfrom(int s ,void *buf,size_t len,int flags,struct sockaddr *from,socklen_t *fromlen);
//與函數recv功能類似,只是函數recv只能用于面向連接的套接字,而函數recvfrom沒有此限制,可以用于從無連接的套接字上接收數據
//參數buf指向接收緩沖區
//參數len指定了緩沖區的大小
//參數flags是控制選項,含義與recv中的一致
//如果參數from非空,且該套接字不是面向連接的,則函數recvfrom返回時,參數from中將保存數據的源地址
//參數fromlen在調用recvfrom前為參數from的長度,調用recvfrom后將保存from的實際大小
關閉套接字函數:
int close(int fd);
//參數fd為一個套接字描述符;
函數 int shutdown(int s,int how) 功能與close類似,但是shutdown功能更強大,它允許對套接字進行單向關閉或全部禁止,參數s為待關閉的套接字描述符,參數how指定了關閉的方式。
inet系列函數用于網絡地址的格式轉換;獲取和設置套接字屬性函數:
int getsockopt(int s,int level,int optname,void *optval,cocklen_t *optlen);
int setsockopt(int s,int level,int optname,const void *optval,socklen_t optlen);
//參數s為一個套接字
//參數level是進行套接字選項操作的層次
//參數optname是套接字選項名稱
//對于函數getsockopt,參數opval用來存放獲得的套接字選項,參數optlen在調用函數前其值為optval指向的空間的大小,調用完后則其值為參數optval所保存的結果的實際大小
//對于函數setsockopt,參數optval是待設置的套接字選項的值,參數optlen是選項的長度
多路復用函數:
int select(int n,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);
//參數n是需要監視的文件描述符數
//參數readfds指定需要監視的可讀文件描述符集合
//參數writefds指定需要監視的可寫文件描述符集合
//參數exceptfds指定需要監視的異常文件描述符的集合
//參數timeout指定了阻塞的時間
網絡編程中有很多新的概念和協議,要好好理解。還有一些系統定義的數據類型,要了解這些數據類型,方便使用。其次是要掌握一些常用函數的功能及使用方法,網絡編程我剛剛開始接觸,感覺跟前面有很大區別,必須進一步學習才能有所提高。