UNIX网络编程_socket介绍
这篇笔记记录什么socket的认识。
1 什么是socket
socket可以看成是用户进程与内核网络协议栈的编程接口。 上图中,Application是用户空间,TCP IP是内核空间,用户空间想要访问内核中的网络协议,就要通过Socket接口。 socket不仅可以用于本机的进程间通信,还可以用于网络上不同主机的进程间通信。比如,手机和电脑之间也可以通过网络进行通信。
2 IPV4套接字地址结构
ipv4接口有两种结构,分别是 网络套接字结构和通用套接字结构。
网络套接字地址结构
IPV4套接字地址结构通常也称为“网际套接字地址结构”,以sockaddr_in命名。
struct sockaddr_in { uint8_t sin_len; sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; char sin_zero[8]; };
sin_len:整个sockaddr_in结构体的长度; sin_family:指定该地址家族,在这里必须设为AF_INET; sin_port:端口 sin_addr:IPv4的地址; sin_zero:暂不使用,一般将其设置为0;
通用套接字结构
struct sockaddr { uint8_t sin_len; sa_family_t sin_family; char sa_data[14]; };
sin_len: 整个sockaddr结构体的长度 sin_family: 指定该地址家族 sa_data: 由sin_family决定它的形式。
3 大小端
大端字节序:最高有效位存储于最低内存位置。 小端字节序:最高有效位存放在内存最高位置。 主机字节序:不同主机有不同字节序,大段和小端。 网络字节序:通常为大端字节序。
#include <stdio.h> int main() { unsigned int x = 0x12345678; unsigned char *p = (unsigned char *)&x; printf("%0x %0x %0x %0x ", p[0], p[1], p[2], p[3]); return 1; }
12是最高有效位,存放在了高地址p[3],所以是小端字节序。
4 字节转换函数
从网络端发送 h表示Host主机, n表示network, s表示short, l表示 long int
uint32_t htonl(uint32_t hostlong);将32位主机序转为网络字节序; uint16_t htons(uint16_t hostshort); 将16位主机序转为网络16位。 uint32_t ntohl(uint32_t netlong); 将32位网络字节序转为32主机字节序; uint16_t ntohs(uint16_t netshort); 将16位网络字节序转为16位主机字节序。
代码
#include <stdio.h> #include <arpa/inet.h> int main() { unsigned int x = 0x12345678; unsigned char *p = (unsigned char *)&x; printf("%0x %0x %0x %0x ", p[0], p[1], p[2], p[3]); // 输出结果 78 65 45 34 12 // 将主机字节序转为网络字节序 unsigned int y = htonl(x); p = (unsigned char *)&y; printf("%0x %0x %0x %0x ", p[0], p[1], p[2], p[3]); // 输出结果 12 34 56 78 return 1; }
5 地址转换函数:int 转为 const char *
**将32位整数转为const char ***
in_addr_t inet_addr(const char *cp); // 将主机地址转为32位整数,比如192.168.1.1 转为 32位 整数, 发送数据时候,需要这样转换。 char *inet_ntoa(struct in_addr in); // 将地址结构转为点分十进制ip地址。 int inet_aton(const char *cp, struct in_addr *inp);
#include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> int main() { unsigned int addr = inet_addr("192.168.1.1"); // char * 转 uint printf("addr=%u ", ntohl(addr)); // 将网络字节序转为主机字节序 printf("addr=%u ", addr); // 将地址结构转为 点分十进制 struct in_addr ipaddr; ipaddr.s_addr = addr; printf("addr=%s ", inet_ntoa(ipaddr)); // uint转char * return 1; }
6 套接字类型
-
流式套接字(SOCK_STREAM) 提供面向连接的、可靠的数据传输服务,数据无差错,无重复的发送,且按发送顺序接收。 数据报式套接字(SOCK_DGRAM) 提供无连接服务。不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。