* @li AF_UNIX, AF_LOCAL 本机通信
* SOCK_RAW 原始套接字(IP、ICMP)
* @param[in] protocol 指定使用协议,通常是0
int socket(int domain, int type, int protocol);
2. 绑定ip地址(本机)和端口(自己的端口)到监听socket 放SIM卡
* @brief 绑定ip地址(本机的)和端口(自己的)到socket
* @param[in] addr 地址(通信类型、ip地址和端口号)
* @param[in] addrlen addr的字节数
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
3. listen(将socket设置为监听模式) 开机
* @param[in] backlog 设置listen队列的最大连接请求个数
int listen(int sockfd, int backlog);
4. accept(接收客户端连接, 创建客户端socket) 接通
* @brief 接收客户端连接, 创建跟客户端连接的socket
* @param[in] sockfd 监听套接字
* @param[out] addr 客户端地址(ip地址和端口)
* @param[in | out] addrlen 输入地址缓存的字节数,输出实际地址的字节数
* @notes listen请求队列为空时,在阻塞模式下,本函数会阻塞
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
* @param[in] sockfd 客户端套接字
* @notes 一个字节都无法发送时,在阻塞模式下,本函数会阻塞
* send(sockfd, buf, len, 0) <===> write(sockfd, buf, len);
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
* @brief 接收数据(读取数据从接收中缓冲区)
* @param[in] sockfd 客户端套接字
* @param[out] buf 放置数据的缓冲
* @notes 一个字节都无法接收时,在阻塞模式下,本函数会阻塞
* recv(sockfd, buf, sizeof(buf), 0) <===> read(sockfd, buf, sizeof(buf));
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
int shutdown(int sockfd, int how);
2. 绑定ip地址(本机)和端口(自己的端口)到socket(可选)
* @param[in] addr 服务端地址(ip和端口)
* @param[in] addrlen 地址字节数
* @notes 正在连接时,在阻塞模式下,本函数会阻塞,但阻塞有超时时间
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
打包(数据组合) 1. 结构体 2. 按顺序放数据到缓存
字节序 小端 大端 func会错误,func有四个字节,字节顺序正好相反 统一使用大端(htonl/ntohl htons/ntohs)
位数 32bit 64bit 机器理解int类型的时候,位数不同 系统没有提供统一方法,程序自己保证位数相同
对齐 32bit 64bit 因为结构体程序对齐,很可能导致中间,空闲的字节 认真设计结构体,是它尽量不出现因为需要对齐,而空出内存
对于初学者,如果需要考虑数据传输完全正确,不要使用结构体。