地址:
#include <sys/socket.h>
struct sockaddr{
unsigned short sa_family;
char sa_data[MAXSOCKADDRDATA];
};
一、基本套接字操作
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
AF_UNIX PF_UNIX
AF_INET PF_INET
AF_INET6 PF_INET6
SOCK_STREAM,SOCK_DGRAM,SOCK_RAW
IPPROTO_ICMP,IPPROTO_ICMPV6,IPPROTO_IPIP,IPPROTO_IPV6,IPPROTO_RAW,IPPROTO_TCP,IPPROTO_UDP
int bind(int sock, struct sockaddr *my_addr, socklen_t addrlen);
int listen(int sock, int baklog);
int accept(int sock, struct sockaddr*addr, socklen_t *addr_len);EAGAIN
int connect(int sock, struct sockaddr *serveraddr, socklen_t addrlen);
连接完成之后可以通过以下函数获得本地、远程sock地址信息:
int getpeername(int s, struct sockaddr*addr, socklen_t *addr_len);
int getsockname(int s, struct sockaddr*addr, socklen_t *addr_len);
UNIX 域套接字(只能在本机中使用)
unix 域地址
EADDRINUSE
#include <sys/socket.h>
#include <sys/un.h>
struct sockaddr_un{
unsigned short sun_family;
char sun_path[UNIX_PATH_MAX];
};
UNIX_PATH_MAX=108
通过域套接字传递文件描述符
int socketpair(int domain, int type, int protocol, int sockfds[2]);
int sendmsg(int fd, const struct msghdr *msg, unsigned int flags);
int recvmsg(int fd, struct msghdr *msg, unsigned int flags);
struct msghdr{
void *msg_name;
unsigned int msg_namelen;
struct iovec *msg_iov;
unsigned int msg_iovlen;
void *msg_control
unsigned int msg_constrollen;
int msg_flags;
};
struct cmsghdr{
unsigned int cmsg_len;
int cmsg_level;
int cmsg_type;
int cmsg_data[0];
};
SOL_SOCKET, SCM_RIGHTS;
二、TCP/IP协议簇
字节存储顺序:
网络传输字节顺序采用大端;
#include <netinet/in.h>
unsigned int htonl(unsigned int hostlong);//主机----->网络字节
unsigned short htons(unsigned short hostshort);//主机----->网络字节
unsigned int ntohl(unsigned int neglong);//网络字节顺序------->主机顺序
unsigned short ntohs(unsigned short netshort);//网络字节顺序------->主机顺序
地址+端口号----->唯一标识TCP/IP的端点(连接)
/etc/services---->端口号跟协议名的映射,范围:0----65535
IPV4地址格式(点分十进制):
struct sockaddr_in
{
short int sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
};
IPV6地址格式(十六进制格式):
struct sockaddr_in6
{
short int sin6_family;
unsigned short int sin6_port;
unsigned int sin6_flowinfo;
struct in6_addr sin6_addr;
unsigned int sin6_scope_id;
};
IP地址可读形式与二进制格式转换:
const char *inet_ntop(int family, const void*address, char *dest, int size);//二进制----->点分十进制
int inet_pton(int family, const char*address, void *dest);//点分十进制----->二进制
//转换名称到地址:将主机名/服务名加入到IP地址列表中
int getaddrinfo(const char *hostname, const char *servicename, const struct addrinfo *hints, struct addrinfo **res);
struct addrinfo{
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
socklen_t ai_addrlen;
struct sockaddr_t *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};//该结构一般来说,只有前四个成员有用,其他设为NULL;
void freeaddrinfo(struct addrinfo *res);//释放addr信息
getaddrinfo()出错号,应通过const char*gai_strerror(int error);打印错误信息;
//获得IP相对应的主机或服务名
#include <sys/socket.h>
#include <netdb.h>
int getnameinfo(struct sockaddr *addr, socklen_t addrlen, char *hostname,
size_t hostlen,char *servicename, size_t servicelen, int flags);
可能错误码:EAI_OVERFLOW,NL_DGRAM,NI_NAMEREQD, NI_NOFQDN,NI_NUMERICSERW,NI_NUMERICSERV
发送、接收函数:
int send(int sockfd, const void *data, size_t len, int flags);
int sendto(int sockfd, const void *data, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
int recv(int sockfd, const void *data, size_t maxlen, int flags);
int recvfrom(int sockfd, const void *data, size_t maxlen, int flags, const struct sockaddr *from, socklen_t fromlen);
套接字错误:
EADDRINUSE://已被使用
EADDRNOTAVAIL://请求的地址无效
EAFNOSUPPORT://地址族不支持
ECONNABORTED,ECONNREFUSED,ECONNRESET,EDESTADDRREQ,
EHOSTDOWN,EHOSTUNREAD,EISCONN
常用旧的网络函数:
char *inet_ntoa(struct in_addr_address);ipv4结构地址--->点十分进制
unsigned long int inet_addr(const char *address);//点十分进制---->二进制
int inet_aton(const char *ddaddress, struct in_addr *address);//二进制存储至address中
struct hostent *gethostbyname(const char*name);//返回主机名
struct hostent *gethostbyaddr(const char *addr,int len,int type);//返回主机的地址