1. socket地址
1)big endian & little endiana. 现代PC大多采用little endian字节序。
b. JVM采用big endian。
2)Linux给TCP/IP协议族提供了socket专用的sockaddr_in地址结构
struct sockaddr
{
sa_family_t sa_family;
char sa_data[14];
};
struct sockaddr_in
{
sa_family_t sin_family;
u_int16_t sin_port;
struct in_addr sin_addr;
};
struct in_addr
{
u_int32_t s_addr; /*用网络(big endian)字节序表示的IPv4地址整数*/
};
3)IP地址转换
#include <arpa/inet.h>
in_addr_t inet_addr(const char* strptr); /* 将点分十进制字符串表示的IPv4地址转化为用网络字节充整数表示的地址 */
int inet_aton(const char* cp, struct in_addr* inp); /* 同inet_addr,但结果保存到inp中 */
char* inet_ntoa(struct in_addr in); /* inet_ntoa内部采用static内存来保存结果,所以它不可重入 */
4)PORT转换
htons();
ntohs();
2. 操作socket
1) 创建socket2) 命名socket(即绑定地址)
3) 监听socket
4) 接受连接
5) 发起连接
6) 关闭连接
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol); /* 返回socket文件描述符 */
int bind(int socketfd, const struct sockaddr* my_addr, socklen_t addrlen); /* Server才需要bind,Client不需要 */
int listen(int sockfd, int backlog); /* 创建一个内核监听Queue,backlog指定其最大长度,Server被动接收连接 */
int accept(int sockfd, struct scokaddr* addr, socklen_t* addrlen); /* 执行成功则返回一个连接socket,用于后面的通信 */
int connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen); /* Client主动向Sever发起连接 */
int close(int fd); /*将对socket的引用-1*/
int shutdown(int sockfd, int howto); /*立即关掉socket*/
7)读写数据
TCP version
ssize_t recv(int sockfd, void* buf, size_t len, int flags);
ssize_t send(int sockfd, const void* buf, size_t len, int flags);
UDP version
ssize_t recvfrom(int sockfd, void* buf, size_t len, int flags, struct sockaddr* src_addr, socklen_t* addrlen);
ssize_t sendto(int sockfd, const void* buf, size_t len, const struct sockaddr& dest_addr, scoklen_t addrlen);
8)地址信息函数
int getsockname(int sockfd, struct sockaddr* address, socklen_t* address_len); /* 获取本端socket地址 */
int getpeername(int sockfd, struct sockaddr* address, socklen_t* address_len); /* 获取远端socket地址 */
9)获取/设置socket属性
int getsockopt(int sockfd, int level, int option_name, void* option_value, socklen_t* restrict option_len);
int setsockopt(int sockfd, int level, int option_name, const void* option_value, socklen_t option_len);
3. 获取网络信息
#include <netdb.h>
/* 不可重入 */
struct hostent* gethostbyname(const char* name); /* 根据主机名获取主机的完整信息 */
struct hostent* gethostbyaddr(const void* addr, size_t len, int type); /* 根据IP获取主机的完整信息 */
struct servent* getservbyname(const char* name, const char* proto); /* 根据名称获取某服务的完整信息 */
struct servent* getservbyport(int port, const char* proto); /* 根据端口号获取某服务的完整信息 */
/* 可重入, re-entrant */
struct hostent* gethostbyname_r(const char* name);
struct hostent* gethostbyaddr_r(const void* addr, size_t len, int type);
struct servent* getservbyname_r(const char* name, const char* proto);
struct servent* getservbyport_r(int port, const char* proto);
int getaddrinfo(const char* hostname, const char* service, const struct addrinfo* hints, \
struct addrinfo** result); /* 根据主机名获取IP(gethostbyname/gethostbyname_r),或者根据服务名称获取端口号(getservbyname/getservbyname_r) */
int getnameinfo(const struct sockaddr* sockaddr, socklen_t addrlen, char* host, socklen_t hostlen, \
char* serv, socklen_t servlen, int flags); /* 根据socket地址同时获取字符串表示的主机名和服务名(gethostbyaddr/gethostbyaddr_r, getservbyport/getservbyport_r) */