1.套接字的基本结构
数据定义:
struct sockaddr {
unsigned short sa_family; /* address族, AF_xxx */
char sa_data[14]; /* 14 bytes的协议地址 */
};
sa_family 一般来说,都是“AFINET”。
sa_data 包含了一些远程电脑的地址、端口和套接字的数目,它里面的数据是杂溶在一
切的。
为了处理struct sockaddr, 程序员建立了另外一个相似的结构 struct sockaddr_in:
struct sockaddr_in (“in” 代表 “Internet”)
struct sockaddr_in {
short int sin_family; /* Internet地址族 */
unsigned short int sin_port; /* 端口号 */
struct in_addr sin_addr; /* Internet地址 */
unsigned char sin_zero[8]; /* 添0(和struct sockaddr一样大小)*/
};
这个结构提供了方便的手段来访问socket address(struct sockaddr)结构中的每一个元
素
2.套接字字节转换程序的列表:计算机内存中有两种数据存储方式,一种为小端字节序,也就是低地址存储数据低字节,高地址存储数据高字节;一种为大端字节序,也就是低地址存储高字节,高地址存储低字节。网络字节序采用大端字节序,而主机字节序有可能为小端字节序,因此,存在着字节序的转换问题。
l htons()——“Host to Network Short”主机字节顺序转换为网络字节顺序(对无符号
短型进行操作4 bytes)
l htonl()——“Host to Network Long” 主机字节顺序转换为网络字节顺序(对无符
号长型进行操作8 bytes)
l ntohs()——“Network to Host Short “ 网络字节顺序转换为主机字节顺序(对无符
号短型进行操作4 bytes)
l ntohl()——“Network to Host Long “ 网络字节顺序转换为主机字节顺序(对无符
号长型进行操作8 bytes)
3. IP 地址转换
in_addr_t inet_addr(const char *straddr);
int inet_aton(const char* straddr,struct in_addr *addrp);
char* inet_ntoa(struct in_addr inaddr);
头文件:sys/socket.h netinet/in.h arpa/inet.h
inet_addr成功返回32位网络字节序地址,出错返回INADDR_NONE。INADDR_NONE为linux定义的一个常数,是一个不存在的ip地址;
inet_aton将ASCII转换成网络字节序的32位二进制值,输入的ASCII放在straddr中,转换后放在addrp中,成功返回1,失败返回0;
inet_ntoa将32位二进制地址转换成ASCII地址,成功返回ASCII值,失败返回NULL。
Linux 系统提供和很多用于转换IP 地址的函数.首先,假设你有一个struct sockaddr_in ina,并且你的IP 是166.111.69.52 ,你想把你的IP 存储到ina 中。你可以使用的函数: inet_addr() ,它能够把一个用数字和点表
示IP 地址的字符串转换成一个无符号长整型。你可以像下面这样使用它:
ina.sin_addr.s_addr = inet_addr(“166.111.69.52”);
注意:
l inet_addr() 返回的地址已经是网络字节顺序了,你没有必要再去调用htonl() 函数
反过来,如果你有一个struct in_addr 并且你想把它代表的IP 地址打印出来(按照数字.数字.数字.数字的格式),那么你可以使用函数inet_ntoa()(“ntoa”代表“Network to ASCII”),它会把struct in_addr 里面存储的网络地址以数字.数字.数字.数字的格式。
l inet_ntoa() 使用struct in_addr 作为一个参数,不是一个长整型值。
4.字节操作函数
字节操作函数主要是用于读取结构体中的某几个字节。
void bzero(void *dest,size_t nbytes);
void bcopy(const void *src,void *dest,size_t nbytes);
int bcmp(const void *prt1,const void *ptr2,size_t nbytes);
void *memset(void *dest,int c,size_t len);
void *memcpy(void *dest,const void *src,size_t nbytes);
int memcmp(const void *ptr1,const void ptr2,size_t nbytes);
头文件:string.h
说明:以b打头的函数为支持套接口函数的系统所提供,mem为支持ANSI C库提供的函数;其中,bzero将制定的起始地址设置为0(nbytes表示字长),bcopy和memcpy为复制,bcmp和memcmp为比较,memset将目标中指定数据的字节设置为指定的值。
5.readn,writen和readline函数
基本TCP客户-服务器程序的套接口函数如下图:
1、socket函数
原型:#include<sys/socket.h>
int socket(int family, int type, int protocol); 返回值:非负描述符--成功, -1--出错;
作用:指定期望的通信协议接口(TCP或UDP或unix域字节协议等)
family 指明协议簇
族 | 解释 |
AF_INET | IPv4协议 |
AF_INET6 | IPv6协议 |
AF_LOCAL | Unix与协议 |
AF_ROUTE | 路由套接口 |
AF_KEY | 密钥套接口 |
类型 | 解释 |
SOCK_STREAM | 字节流套接口 |
SOCK_DGRAM | 数据包套接口 |
SOCK_RAW | 原始套接口 |
protocol参数应设置为某个协议类型常值,或者设为0.
protocol | 说明 |
IPPROTO_TCP | TCP传输协议 |
IPPROTO_UDP | UDP传输协议 |
IPPROTO_SCTP | SCTP传输协议 |
2、connect函数
原型:#include<sys/socket.h>
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);返回值:0---成功,-1----出错;
作用:客户端用connect 函数建立一个与TCP服务器的连接;
参数:sockfd,套接口描述字;
servaddr,套接口地址结构的指针,该地址结构需要包含服务器IP地址和端口号;
addrlen, 套接口地址结构的大小;
关于connect出错返回的几种情况:原型:#include<sys/socket.h>
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);返回值:0---成功,-1----出错;
作用:给套接口分配一个本地协议地址;
4、listen函数
原型:#include<sys/socket.h>
int listen(int sockfd, int backlog); 返回值:0---成功,-1---出错;
作用 : 将未连接的套接口转换成被动套接口,指示内核应接受此套接口的连接请求;第二个参数规定了次套接口排队的最大连接数;
参数:sockfd,套接口描述字;
backlog,套接口排队的最大连接数;
对与第二个参数backlog的理解: