网络技术

面试常见问题05 - Socket 编程

2019-07-13  本文已影响0人  第八天的蝉啊

一. Socket

Socket 工作位置

二. 结构体

1.1 struct in_addr:32位IP地址

struct in_addr {
  unsigned long s_addr;  // 32位IP地址,4字节
};

1.2 struct sockaddr

struct sockaddr {
    unsigned short sa_family;    // 地址家族,通常为AF_INET,2字节
    char sa_data[14];            // 目标地址和端口,14字节
};

1.3 struct sockaddr_in:

struct sockaddr_in {
  short int sin_family;         // 通信类型,通常为AF_INET,2字节
  unsigned short int sin_port;  // 端口,2字节
  struct in_addr sin_addr;      // Internet 地址,4字节
  unsigned char sin_zero[8];    // 为保证与sockaddr结构的长度相同,8字节
};

三. 字节顺序转换

2.1 网络字节序与主机字节序

主机字节序就是常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指
整数在内存中保存的顺序,这个叫做主机序。引用标准的Big-Endian和Little-Endian的
定义如下:
a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

网络字节序:4个字节的32 bit值以下面的次序传输:首先是0 ~ 7bit,其次8 ~ 15bit,
然后16~23bit,最后是24~31bit。这种传输次序称作大端字节序。由于TCP/IP首部中所有
的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。字节序,顾名思
义字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序,一个字节的数据没有顺序
的问题了。

所以: 在将一个地址绑定到socket的时候,请先将主机字节序转换成为网络字节序,而不要
假定主机字节序跟网络字节序一样使用的是Big-Endian

2.2 h-host(本机),n-network(网络),s-short(短整型),l-long(长整型)

1)htons() -- "Host to Network Short"
2)htonl() -- "Host to Network Long"
3)ntohs() -- "Network to Host Short"
4)ntohl() -- "Network to Host Long"
5)inet_addr() -- 将IP地址从点数格式转换成无符号长整型的网络字节格式
6)inet_ntoa() -- 将IP地址从长整型转换成点数格式的字符串

四. 常用函数

序号 函数名 功能
1 socket() 创建一个网络套接字,返回套接字描述符
2 bind() 为指定的套接字绑定IP地址和端口
3 listen() 让指定的套接字监听通过bind()绑定的端口
4 accept() 创建并返回一个文件描述符与listen()监听到的连接请求连接
5 recv() 用于流式套接字通讯中接收数据
6 send() 用于流式套接字通讯中发送数据
7 connect() 将指定的套接字连接到指定的IP地址和端口
8 sendto() 用于数据报套接字通讯中发送数据
9 recvfrom() 用于数据报套接字通讯中接收数据
10 close() 关闭已打开的套接字
11 shutdown()
12 getpeername()
13 gethostname()

4.1 socket() 函数

1)domain:协议族,决定了socket的地址类型,常用的协议族有:AF_INET、AF_INET6、
           AF_LOCAL、AF_ROUTE,AF_INET决定了要用ipv4地址与端口号的组合
2)type:套接字类型,通常为SOCK_STREAM(流式类型)和SOCK_DGRAM(数据报类型)
3)protocol:指定协议,常用的协议有:IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、
             IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协
             议、TIPC传输协议

4.2 bind() 函数

1)sockfd:socket 返回的文件描述符
2)my_addr:指向保存着 IP 地址和本地端口的数据结构 struct sockaddr 的指针
3)addrlen:设置为 sizeof(struct sockaddr)

PS:
my_addr结构体中的sin_port 和sin_addr.s_addr需要转换为网络字节顺序
my_addr.sin_port = htons(0);    // 随机选择一个没有使用的端口
my_addr.sin_addr.s_addr =  htonl(INADDR_ANY);  // 使用自己的IP地址

4.3 listen() 函数

1)sockfd:socket 返回的文件描述符
2)backlog:进入队列中允许的连接数目

PS:进入的连接是在队列中等待直到调用 accept() 接受连接

4.4 accept() 函数

1)sockfd:socket 返回的文件描述符
2)addr:指向保存着请求连接的源 IP 地址和源端口的数据结构 struct sockaddr_in 的指针
3)addrlen:指向值为 sizeof(struct sockaddr) 的局部变量 的指针

PS:通过改变 addrlen 指向的局部变量的值来说明写入到addr的字节数

4.5 recv() 函数

1)sockfd:要读的套接字描述符(socket() 或 accept() 返回的)
2)buf:指向要读的信息的缓冲的指针
3)len:缓冲的最大长度
4)flags:通常设置为0

4.6 send() 函数

1)sockfd:发送数据的套接字描述符(socket() 或 accept() 返回的)
2)msg:指向发送的数据的指针
3)len:发送的数据的长度
4)flags:通常设置为0

4.7 connect() 函数

1)sockfd:socket 返回的文件描述符
2)serv_addr:保存着目的端口和 IP 地址的数据结构 struct sockaddr
3)addrlen:设置为 sizeof(struct sockaddr)

PS:无需使用bind()绑定本地端口,内核将自动选择一个合适的端口号

4.8 sento() 函数

1)sockfd:socket() 返回的发送数据的套接字描述符
2)msg:指向发送的数据的指针
3)len:发送的数据的长度
4)flags:通常设置为0
5)to:指向包含了目的 IP 和端口信息的 struct sockaddr 的指针
6)tolen:通常设置为 sizeof(struct sockaddr)

PS:无需使用bind()绑定本地端口,内核将自动选择一个合适的端口号

4.9 recvfrom() 函数

1)sockfd:socket() 返回的要读的套接字描述符
2)buf:指向要读的信息的缓冲的指针
3)len:缓冲的最大长度
4)flags:通常设置为0
5)from:指向包含源 IP 地址和端口信息的 struct sockaddr 的指针
6)fromlen:指向值为 sizeof(struct sockaddr) 的局部变量的指针

PS:通过改变 fromlen 指向的局部变量的值来说明写入到 from 的字节数

4.10 close() | shutwodn() 函数

1)sockfd:要关闭的套接字描述符
2)how 的值是下面的其中之一:
   0 – 不允许接受
   1 – 不允许发送
   2 – 不允许发送和接受(和 close() 一样)

PS:
1)close() 防止套接字上更多的数据的读写。任何在另一端读写套接字的企图都将返回错误信息
2)如果在无连接的数据报套接字中使用 shutdown(),只是让 send() 和 recv() 不能使用(数据报
   套接字中使用了 connect 后 是可以使用它们的)

4.11 getpeername() 函数

1)sockfd:连接的流式套接字的描述符
2)addr:指向 struct sockaddr (或 struct sockaddr_in) 的指针,保存连接的另一边的信息
3)addrlen:指向值为 sizeof(struct sockaddr) 的局部变量的指针

PS:通过设置 addr,获得在连接的流式套接字上谁在另外一边

4.12 gethostname() 函数

1)hostname:字符数组指针,在函数返回时保存主机名
2)size:hostname 数组的字节长度

PS:通过设置 hostname,获得程序所运行的机器的主机名字,然后可以使用 gethostbyname() 
    获得机器的 IP 地址

五. socket 中 TCP 连接的建立和断开

5.1 三次握手建立连接详解

TCP三次握手

5.2 四次握手释放连接详解

TCP四次挥手
上一篇下一篇

猜你喜欢

热点阅读