面试题汇总
1. 判断大小端问题
大端:低字节存放在高地址; 小端:低字节存放在低地址 如 : 0x12345678
bool is_little_endian() {
unsigned int x = 1;
return ((char*)&x)[0];
}
bool is_big_endian() {
unsigned int x = 1;
return !((char*)&x)[0];
}
2. 简要说明UDP数据包包含哪几个部分,画图说明也可以。
源端口号:标识发送方的端口号。
目的端口号:标识接收方的端口号。
长度:表示UDP数据包的总长度。
校验和:用于检测传输错误。
数据:携带应用程序的数据。
检验和:用于检测UDP数据包在传输过程中是否发生错误。校验和覆盖UDP头部和数据部分。
2.多任务系统环境下经常用到函数阻塞和非阻塞状态,其区别是什么?
阻塞函数会让当前线程(或进程)处于等待状态,在等待期间,当前线程无法执行其他任务,可能会导致系统资源的浪费,如accept()没新客户端连接,会阻塞。
非阻塞函数不会让当前任务等待,而是立即返回结果,如果没有准备好的数据或资源,非阻塞函数通常返回一个错误代码(例如 -1
或 EAGAIN
)。
3. 简单写出多路复用select() 的使用流程。
// 初始化文件描述符集合
fd_set readfds; // 新建一个文件描述符集合
FD_ZERO(&readfds); // 把集合清空
FD_SET(server_fd, &readfds); // 加入 某个描述符
// while 循环里调用select去处理消息
调用select 轮询监视文件描述符集合,返回有反应的描述符数量。
int activity = select(maxfd + 1, &tempfds, NULL, NULL, NULL);
用户再遍历文件描述符,处理有反应的描述符(判断是否有新描述符,有新的就加到描述符表中,并更新max_fd,否则就直接recv接收数据,如果返回0说明客户端关闭了,关掉描述符,并从表中删除)
for (int i = 0; i < max_fd + 1; ++i) {
if (FD_ISSET(i, &bak_fds)) {
if (i == listen_fd) {
new_fd = accept(listen_fd, NULL, NULL);
if (new_fd < 0) {
perror("accept");
break;
}
printf("Have a new connection!\n");
FD_SET(new_fd, &r_fds);
max_fd = max_fd < new_fd ? new_fd : max_fd;
} else {
len = recv(i, buf, sizeof(buf), 0);
if (len < 0) {
perror("rcv");
FD_CLR(i, &r_fds);
close(i);
break;
}
if (len == 0) { // 客户端端关闭
printf("remote client closed!\n");
FD_CLR(i, &r_fds);
close(i);
break;
}
buf[len] = 0;
printf("msg: %s\n", buf);
}
}
}
4. Tcp/udp区别。谈谈增强UDP传输安全性的策略?
udp是面向数据报,无连接的,不能保证数据的顺序,可能丢包,属于不可靠的传输,速度快。
tcp是面向字节流,有链接的,三次握手,四次挥手,拥塞控制,滑动窗口等保证数据传输稳定可靠。
UDP传输安全性的策略
目前有如下的开源程序实现利用UDP实现了可靠的数据传输 :RUDP、RTP、UDT。
5. 写出socket编程相关的API
// 创建套接字
tcp_socket = socket(AF_INET, SOCK_STREAM, 0); 参数//IPV4,TCP,默认0
udp_socket = socket(AF_INET, SOCK_DGRAM, 0); 参数//IPV4,UDP,默认0
// IPV4地址结构
struct sockaddr_in {
sa_family_t sin_family; // 地址族,AF_INET
in_port_t sin_port; // 端口号,网络字节序
struct in_addr sin_addr; // IP 地址
unsigned char sin_zero[8];// 填充字节,通常不用
};
// 启用端口复用
ret = setsockopt(tcp_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
// 将套接字绑定到本地地址和端口
ret = bind(tcp_socket, (const struct sockaddr *) &self, sizeof(self));
// 如果基于tcp的话,有listen()监听,accept()接收客户端连接, send,recv 发收数据 close()关闭连接
// connect()连接服务器
// 如果基于UDP ,sendto,recvfrom 收发数据
6. TCP三次握手,包头中的标志变化?
在三次握手过程中,主要涉及 SYN 和 ACK 标志。
第一次握手(SYN)客户端:发送一个 TCP 数据包,标志位设置为 SYN=1,ACK=0,序列号(Seq):随机生成的初始序列号 x,
标志(Flags):SYN。
作用:客户端请求建立连接
第二次握手(SYN-ACK)服务器:收到客户端的 SYN 数据包后,回复一个 TCP 数据包,标志位设置为 SYN=1 和 ACK=1。序列号(Seq):服务器随机生成的初始序列号 y,
确认号(Ack):客户端序列号 x + 1,
标志(Flags):SYN | ACK,
服务器确认客户端的请求,并向客户端发送自己的初始序列号。
第三次握手(ACK)客户端:收到服务器的 SYN-ACK 数据包后,发送一个 TCP 数据包,标志位设置为 ACK=1。序列号(Seq):客户端的序列号 x + 1。
确认号(Ack):服务器序列号 y + 1。
标志(Flags):ACK。
作用:客户端确认服务器的 SYN 数据包,完成连接建立。
7. TCP/IP握手建立过程
第一次,客户端向服务器发送SYN同步包请求,第二次:服务器收到请求后,回复一个SYN同步请求,加上一个ACK表示确认请求,第三次,客户端再次回复一个ACK包确认请求。
8. 产生死锁的必要条件是什么?解决死锁有几种方法?
9. 说说http与https区别。
HTTP(超文本传输协议)和HTTPS(安全超文本传输协议)是两种用于网络通信的协议.
HTTP:它允许客户端(如浏览器)与服务器之间进行数据交互。
无法验证通信双方的身份,容易受到伪装攻击,默认使用端口80,URL以http://
开头,传输速度快,因为没有加密和解密的开销。
HTTPS:是HTTP的加密版本,它通过在HTTP的基础上添加SSL/TLS(安全套接层/传输层安全)协议来实现数据的安全传输。
数据通过SSL/TLS加密,确保传输过程中的数据保密性、完整性和身份验证,通过数字证书验证服务器的身份,确保用户与真实服务器通信;默认使用端口443;URL以https://
开头;由于加密和解密过程,性能略低于HTTP,但随着硬件性能的提升,这种差距已经越来越小;
客户端请求:客户端(如浏览器)向服务器发起HTTPS请求。
服务器响应:服务器向客户端发送其SSL证书(包含公钥)。
客户端验证:客户端验证服务器证书的有效性(包括证书颁发机构、证书有效期等)。
密钥交换:客户端生成一个随机的对称密钥(如AES密钥),并使用服务器的公钥加密后发送给服务器。
加密通信:服务器使用私钥解密对称密钥,之后客户端和服务器使用对称密钥进行加密通信,确保数据的安全性。
10. http的状态码
1xx:信息性状态码,表示请求正在处理中。
2xx:成功状态码,表示请求已成功处理。
3xx:重定向状态码,表示客户端需要采取进一步操作。
4xx:客户端错误状态码,表示请求有误或客户端问题。
5xx:服务器错误状态码,表示服务器在处理请求时发生错误。
11. 简述DNS 及解析过程
是互联网中用于将域名(如www.example.com
)转换为IP地址(如93.184.216.34
)的系统