1. 程式人生 > >網路程式設計(二)——伺服器和客戶端資訊的獲取

網路程式設計(二)——伺服器和客戶端資訊的獲取

 

目錄

1、字串IP地址和二進位制IP地址結構的轉換

2.套接字檔案描述符的判定

3、IP地址與域名之間的相互轉換

4、協議名稱處理函式


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