網路程式設計(二)——伺服器和客戶端資訊的獲取
目錄
1、字串IP地址和二進位制IP地址結構的轉換
#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> struct in_addr{ unsigned long int s_addr; } int inet_aton(const char *cp, struct in_addr *inp); /*將點分四段式的IP地址轉為地址結構in_addr值*/ in_addr_t inet_addr(const char *cp); /*將點分四段式的IP地址字串轉為地址結構in_addr值*/ in_addr_t inet_network(const char *cp); /*將字串地址的網路部分轉為地址結構in_addr值*/ char *inet_ntoa(struct in_addr *inp); /*將in_addr結構地址轉為字串*/ struct in_addr net_makeaddr(int net, int host); /*將網路地址和主機地址合為IP地址*/ in_addr_t inet_lnaof(struct in_addr in); /*獲得地址的主機部分*/ in_addr_t inet_netof(struct in_addr in); /*獲得地址的網路部分*/ int inet_pton(int af, const char *src, void *dst); /*根據協議族af將srcz轉為struct in_addr的dst*/ const char *inet_pton(int af, const void *src, char *dst,socklen_t cnt);/*根據協議族af將struct in_addr的src轉為緩衝區大小為cnt的src*/
其中inet_ntoa與inet_addr是不可重入的。
可重入函式可以做這樣的基本定義:重入意味著這個函式可以重複進入,可以被並行呼叫,可以被中斷,它只使用自身棧上的資料變數,它不依賴於任務環境,在多工排程過程中,它是安全的,不必擔心資料出錯。
不可重入函式基本上與可重入函式有相反的定義了:不可重入,意味著不可被並行排程,否則會產生不可預料的結果,這些函式提內一般使用了靜態(static)的資料結構,使用了malloc()或者free()函式,使用了標準I/O函式等等。
例子請參考一下連線:
https://github.com/lixiangsheng2018/linux_network_programming/blob/master/chp8/trans.c
2.套接字檔案描述符的判定
用fstat獲取檔案描述符的模式,然後將模式的S_IFMT部分與S_IFSOCK比較,就可以知道一個檔案描述符是否為socket.
#include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int fstat(int fd, struct stat *buf); struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* inode number */ mode_t st_mode; /* protection */ nlink_t st_nlink; /* number of hard links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ dev_t st_rdev; /* device ID (if special file) */ off_t st_size; /* total size, in bytes */ blksize_t st_blksize; /* blocksize for file system I/O */ blkcnt_t st_blocks; /* number of 512B blocks allocated */ time_t st_atime; /* time of last access */ time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last status change */ };
The following flags are defined for the st_mode field:
S_IFMT 0170000 bit mask for the file type bit fields
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
S_ISUID 0004000 set UID bit
S_ISGID 0002000 set-group-ID bit (see below)
S_ISVTX 0001000 sticky bit (see below)
S_IRWXU 00700 mask for file owner permissions
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 mask for group permissions
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 mask for permissions for others (not in group)
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission
例子請參考一下連線:
https://github.com/lixiangsheng2018/linux_network_programming/blob/master/chp8/issockettype.c
3、IP地址與域名之間的相互轉換
DNS伺服器功能:在主機的名稱和IP地址之間擔任翻譯工作。
#include <netdb.h>
extern int h_errno;
struct hostent *gethostbyname(const char *name);/*不可重入函式*/
#include <sys/socket.h> /* for AF_INET */
struct hostent *gethostbyaddr(const void *addr,socklen_t len, int type);
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses */
}
例子參考一下連線:
https://github.com/lixiangsheng2018/linux_network_programming/blob/master/chp8/get_host.c
4、協議名稱處理函式
#include <netdb.h>
struct protoent *getprotoent(void);/*從協議檔案/etc/protocols中讀取一行*/
struct protoent *getprotobyname(const char *name);/*從協議檔案中找到匹配項*/
struct protoent *getprotobynumber(int proto);/*按照協議型別的值找到匹配項*/
void setprotoent(int stayopen); /*設定協議檔案開啟狀態*/
void endprotoent(void); /*關閉協議檔案*/
struct protoent {
char *p_name; /* official protocol name */
char **p_aliases; /* alias list */
int p_proto; /* protocol number */
}
使用協議族函式的例子:
https://github.com/lixiangsheng2018/linux_network_programming/blob/master/chp8/protocol.c