文章目录
1. 什么是Socket?
Socket 是使用标准 Unix 文件描述符和其它程序通讯的方式。
2.两种常用套接字类型
一种是"Stream Sockets"(流格式)— TCP
一种是"Datagram Sockets"(数据包格式)— UDP
3.结构体
(1) sockaddr
这个结构为许多类型的套接字储存套接字地址信息:
sa_family 表示套接字的协议族类型,TCP/IP协议该值为AF_INET
sa_data 包含套接字中的目标地址和端口信息
struct sockaddr{
unsigned short sa_family; /* 地址家族, AF_xxx */
char sa_data[14]; /*14字节协议地址*/
}
(2) sockaddr_in
为了处理struct sockaddr,程序员创造了一个并列的结构: struct sockaddr_in
- sin_port和 sin_addr 必须是网络字节顺序
struct sockaddr_in {
short int sin_family; /* 通信类型 */
unsigned short int sin_port; /* 端口 */
struct in_addr sin_addr; /* Internet 地址 */
unsigned char sin_zero[8]; /* 与sockaddr结构的长度相同*/
};
(3) in_addr
如果你声明 “ina” 是数据结构 struct sockaddr_in 的实例,那么 “ina.sin_addr.s_addr” 就储 存4字节的 IP 地址(使用网络字节顺序)
struct in_addr {
unsigned long s_addr;
};
4.本机字节顺序转换
htons()–“Host to Network Short”
htonl()–“Host to Network Long”
ntohs()–“Network to Host Short”
ntohl()–“Network to Host Long”
5.IP地址的处理
(1) inet_addr
- 将IP地址从点数格式转换成无符号长整型
// 假设已经有了一个sockaddr_in结构体ina
ina.sin_addr.s_addr = inet_addr("132.241.5.10");
inet_addr()返回的地址已经是网络字节格式,所以无需调用函数htonl()
(2) inet_ntoa
- 将一个in_addr结构体输出成点数格式
a = inet_ntoa(ina.sin_addr)
注意的是它返回的是一个指向一个字符的指针。它是一个由inet_ntoa()控制的静态的固定的指针,所以每次调用 inet_ntoa(),它就将覆盖上次调用时所得的IP地址。
6. socket()函数
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
- domain : 应该设置成AF_INET 和sockaddr_in里的相同
- type : 告诉内核是 SOCK_STREAM 类型还是 SOCK_DGRAM 类型
- protocol : 设置为0即可
- 返回 :socket()会返回以后在系统调用种可能用到的 socket 描述符,错误返回-1
7. bind()函数
将套接字和机器上的一定的端口关联,用listen()来侦听一定端口的数据,这是必要的一步
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
- sockfd : 调用 socket 返回的文件描述符
- my_addr : 指向数据结构 struct sockaddr 的指针,它保存你的地址(即端口和 IP 地址) 信息
- addrlen : 设置为 sizeof(struct sockaddr)