当前位置:首页 > Windows程序 > 正文

Unix网络编程API

2021-03-27 Windows程序

#include <netinet.h>
uint16_t htons(uint16_t host16bitvalue);
uint32_t htonl(uint32_t host32bitvalue);
返回:网络字节序值

uint16_t ntohs(uint16_t net16bitvalue);
uint32_t ntohl(uint32_t net32bitvalue);
返回:主机字节序值

一个测试本机字节序的程序,可参见见unpv12e:intro/byteorder.c。

2.字节操作函数

#include <strings.h>
void bzero(void *dest, size_t nbytes);
void bcopy(const void *src, void *dest, size_t nbytes);
int bcmp(const void *ptr1, const void *ptr2, size_t nbytes);
返回:0—相等,非0—不相等

#include <string.h>
void *memset(void *dest, int c, size_t len);
void *memcpy(void *dest, void *src, size_t nbytes);
int memcmp(const void *ptr1, const void *ptr2, size_t nbytes);
返回:0—相同,>0或<0—不相同;进行比较操作时,假定两个不相等的字节均为无符号字符(unsigned char)。

3.地址转换函数

#include <arpa/inet.h>
int inet_aton(const char *strptr, struct in_addr *addrptr);
返回:1—串有效,0—串有错。

in_addr_t inet_addr(const char *strptr);
返回:若成功,返回32为二进制的网络字节序地址;若有错,则返回INADDR_NONE。

char *inet_ntoa(struct in_addr inaddr);
返回:指向点分十进制数串的指针。

int inet_pton(int family, const char *strptr, void *addrptr);
返回:1—成功;0—输入不是有效的表达格式,-1—出错。

const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
返回:指向结果的指针—成功,NULL—失败。

说明:

inet_aton函数的指针若为空,则函数仍然执行输入串的有效性检查,,但不存储任何结果。

inet_addr的缺陷:出错返回值INADDR_NONE等于255.255.255.255(IPv4的有限广播地址),所以该函数不能处理此地址。
尽量使用inet_aton,不使用inet_addr。

inet_ntoa函数的执行结果放在静态内存中,是不可重入的。

参数family可以是AF_INET,也可以是AF_INET6,若参数family不被支持,则出错,errno置为EAFNOSUPPORT。

指针addrptr是结构指针。

len指定目标的大小,避免缓冲区溢出。如果len太小,则返回一个空指针,errno置为ENOSPC。为有助于规定该大小,有如下定义:
#include <netinet.h>
#define INET_ADDRSTRLEN 16 /*fro IPv4 dotted-decimal */
#define INET6_ADDRSTRLEN 46 /*for IPv6 hex string */

inet_ntop函数的参数strptr不能为空指针,成功时,此指针即是函数的返回值。


实现IPv4版本的inet_pton和inet_ntop的程序,参见:unpv12e:libfree/inet_pton_ipv4.c和libfree/inet_ntop_ipv4.c。

4.readn、writen和readline

函数原型如下:
ssize_t readn(int filedes, void *buff, size_t nbytes);
ssize-t writen(int filedes, void *buff, size_t nbytes);
ssize_t readline(int filedes, void *buff, size_t maxlen);
返回:读写字节数,-1—出错。

实现程序见:unpv12e:lib/readn.c、lib/writen.c、lib/readline1.c和lib/readline.c。

5.测试描述符类型

#include <sys/stat.h>
int isfdtype( int fd, int fdtype);
返回:1—是指定类型,0—不是指定类型,-1—出错。

要测试是否为套接口描述子,fdtype应设为S_IFSOCK。

该函数的一个实现程序,参见unpv12e:lib/isfdtype.c

6.socket函数

#include <sys/socket.h>
int socket(int family, int type, int protocol);
返回:非负描述字—成功,-1—出错。

family指定协议族,有如下取值:

AF_INET     IPv4协议

AF_INET6    IPv6协议

AF_LOCAL    Unix域协议

AF_ROUTE    路由套接口

AF_KEY      密钥套接口

type指定套接口类型:

SOCK_STREAM    字节流套接口

SOCK_DGRAM     数据报套接口

SOCK_RAW       原始套接口

protocol一般设为0,除非用在原始套接口上。

并非所有family和type的组合都是有效的。

AF_LOCAL等于早期的AF_UNIX。

7.connect函数

#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
返回:0—成功,-1—出错。

sockfd是socket函数返回的套接口描述字,servaddr和addrlen是指向服务器的套接口地址结构指针和结构大小。

在调用connect之前不必非得调用bind函数。

如果是TCP,则connect激发TCP的三路握手过程,在阻塞情况下,只有在连接建立成功或出错时该函数才返回,
出错情况:

没有收到SYN分节的响应,在规定时间内经过重发仍无效,则返回ETIMEDOUT;

如果对SYN分节的响应是RST,表示服务器在指定端口上没有相应的服务,返回ECONNREFUSED;

如果发出 SYN在中间路由器上引发一个目的地不可达ICMP错误,在规定时间内经过重发仍无效,则返回EHOSTUNREACH或ENETUNREACH错误。

注意:如果connect失败,则套接口将不能再使用,必须关闭,不能对此套接口再调用函数connect。

8.bind函数

#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *maddr, socklen_t addrlen);
返回:0—成功,-1—出错。

进程可以把一个特定的IP地址捆绑到他的套接口上,但此IP地址必须是主机的一个接口。

对于IPv4,通配地址是INADDR_ANY,其值一般为0;使用方法如下:
struct sockaddr_in servaddr;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

对于IPv6,方法如下:
struct sockaddr_in6 serv;
serv.sin6_addr = in6addr_any; (系统分配变量in6addr_any并将其初始化为常值IN6ADDR_ANY_INIT。)

如果让内核选择临时端口,注意的是bind并不返回所选的断口值,要得到一个端口,必须使用getsockname函数。

bind失败的常见错误是EADDRINUSE(地址已使用)。

9.listen函数

#include <sys/socket.h>
int listen(int sockfd, int backlog);
返回:0—成功,-1—出错。

listen把未连接的套接口转化为被动套接口,指示内核应接受指向此套接口的连接请求。第二个参数规定了内核为此套接口排队的最大连接数。

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/68282.html