腾讯面试准备-2024.4.3

腾讯面试准备-2024.4.3

自我介绍

略。

进程与线程怎么通信?

在C++中,父进程与子线程通信可以通过多种方式实现,例如使用全局变量、管道(pipe)、共享内存(shared memory)、消息队列(message queue)等。以下是使用全局变量和条件变量实现的一个简单例子:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
 
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
 
void child_task() {
    std::unique_lock<std::mutex> lock(mtx);
    // 子线程处理任务...
    std::cout << "Child thread is processing task..." << std::endl;
    // 模拟任务处理完毕
    std::this_thread::sleep_for(std::chrono::seconds(1));
 
    ready = true; // 设置标志
    cv.notify_one(); // 通知父进程
}
 
int main() {
    std::thread child_thread(child_task);
 
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [](){ return ready; }); // 父进程等待通知
 
    std::cout << "Parent thread received notification from child." << std::endl;
    // 父进程处理通知后的任务...
 
    child_thread.join(); // 等待子线程完成
    return 0;
}

cookie 和 session 的关系

session

简单的说,当你登陆一个网站的时候,如果web服务器端使用的是session,那么所有的数据都保存在服务器上,客户端每次请求服务器的时候会发送当前会话sessionid,服务器根据当前sessionid判断相应的用户数据标志,以确定用户是否登陆或具有某种权限。由于数据是存储在服务器上面,所以你不能伪造。

SessionId的工作原理:

  1. 浏览器端第一次发送请求到服务器端,服务器端创建一个Session,同时会创建一个特殊的Cookie(name为JSESSIONID的固定值,value为session对象的ID),然后将该Cookie发送至浏览器端
  2. 浏览器端发送第N(N>1)次请求到服务器端,浏览器端访问服务器端时就会携带该name为JSESSIONID的Cookie对象
  3. 服务器端根据name为JSESSIONID的Cookie的value(sessionId),去查询Session对象,从而区分不同用户。有4种情况:
    • name为JSESSIONID的Cookie不存在(关闭或更换浏览器),返回1中重新去创建Session与特殊的Cookie
    • name为JSESSIONID的Cookie存在,根据value中的SessionId去寻找session对象
    • value为SessionId不存在(Session对象默认存活30分钟),返回1中重新去创建Session与特殊的Cookie
    • value为SessionId存在,返回session对象
      在这里插入图片描述

Session的工作原理图:

在这里插入图片描述

cookie

sessionid是服务器和客户端连接时候随机分配的,如果浏览器使用的是cookie,那么所有数据都保存在浏览器端,比如你登陆以后,服务器设置了cookie用户名,那么当你再次请求服务器的时候,浏览器会将用户名一块发送给服务器,这些变量有一定的特殊标记。服务器会解释为cookie变量,所以只要不关闭浏览器,那么cookie变量一直是有效的,所以能够保证长时间不掉线。

如果你能够截获某个用户的cookie变量,然后伪造一个数据包发送过去,那么服务器还是认为你是合法的。所以,使用cookie被攻击的可能性比较大。

如果cookie设置了有效值,那么cookie会保存到客户端的硬盘上,下次在访问网站的时候,浏览器先检查有没有cookie,如果有的话,读取cookie,然后发送给服务器。

假如你在机器上面保存了某个论坛cookie,有效期是一年,如果有人入侵你的机器,将你的cookie拷走,放在他机器下面,那么他登陆该网站的时候就是用你的身份登陆的。当然,伪造的时候需要注意,直接copy cookie文件到 cookie目录,浏览器是不认的,他有一个index.dat文件,存储了 cookie文件的建立时间,以及是否有修改,所以你必须先要有该网站的 cookie文件,并且要从保证时间上骗过浏览器。

Cookie的工作原理:

  1. 浏览器端第一次发送请求到服务器端
  2. 服务器端创建Cookie,该Cookie中包含用户的信息,然后将该Cookie发送到浏览器端
  3. 浏览器端再次访问服务器端时会携带服务器端创建的Cookie
  4. 服务器端通过Cookie中携带的数据区分不同的用户

在这里插入图片描述

异同

相同点:cookie和session都是用来跟踪浏览器用户身份的会话方式。都可以用来存私密的东西。

不同点:cookie数据保存在客户端,session数据保存在服务端。session过期与否,取决于服务器的设定。cookie过期与否,可以在cookie生成的时候设置进去。

怎么选择?

cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,如果主要考虑到安全应当使用session。

session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用cookie。

单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的cookie不能3K。

建议:将登陆信息等重要信息存放为session;其他信息如果需要保留,可以放在cookie中。

加密与 CA 的关系

密钥认证和CA认证是网络通信中常见的两种安全认证方式。密钥认证是指在通讯开始前,客户端和服务器双方各自生成一对公私密钥,并将自己的公钥发送给对方,然后通过公钥加密明文,在对方接收到密文后使用自己的私钥解密还原明文。这种认证方法简单、高效,但安全性不高,容易遭受中间人攻击。而CA认证则是由权威认证机构进行的认证,该认证机构会对申请者进行身份验证,并提供数字证书来证明申请者身份的真实性。因此,CA认证具有更高的安全性。

密钥认证和CA认证有着密切的关系。在网络通信中,密钥认证主要用于加密通讯过程中的数据,确保数据传输的安全性;而CA认证则是用于验证通讯双方的身份,确保双方身份的真实性和可信度。因此,在实际应用中,这两种认证方式通常配合使用,以提高通讯的安全性。

在进行CA认证时,一般需要由权威认证机构颁发数字证书,该证书包括证书申请者的身份信息、公钥等信息。在进行数据加密传输时,客户端会将自己的数字证书发送给服务器,服务器使用数字证书中包含的公钥对数据进行加密。此时客户端可以通过验证数字证书的真实性,确保正在和自己通讯的是真实的服务器,从而防止中间人攻击的发生。

同时,CA认证也可以用于验证网站与应用程序的真实性。在浏览器中打开一个网站时,如该网站已经通过CA认证,并获得颁发的数字证书,则浏览器会确认证书是否有假冒风险,并提醒用户是否信任该网站。这可以帮助用户避免网站钓鱼等恶意攻击。

总的来说,密钥认证和CA认证是网络通信中不可或缺的安全认证方式。在实际应用中,针对不同的安全需求和场景可以选择合适的认证方式,从而提高通讯的安全性。同时,用户也应该了解和加强自身的安全意识,避免因个人操作不当导致的安全问题。

编程题 1:有优先级的括号匹配

问题描述:
在算术表达式中,除了加、减、乘、除等运算外,往往还有括号。包括有大括号 {},中括号 [],小括号 ()。对于每一对括号,必须先左边括号,然后右边括号;如果有多个括号,则每种类型的左括号和右括号的个数必须相等;对于多重括号的情形,按运算规则,从外到内的括号嵌套顺序为:大括号->中括号->小括号,另外相同的括号可以嵌套。

例如,{[()]},{(())},{{}} 为一个合法的表达式,而 ([{}]),{([])},[{<>}] 都是非法的。

代码:

#include <iostream>
#include <stack>
#include <unordered_map>
using namespace std;

unordered_map<char, int> mp = {
	{'{', 4},
	{'}', -4},
	{'[', 3},
	{']', -3},
	{'(', 2},
	{')', -2},
	{'<', 1},
	{'>', -1}};

bool check(string &str)
{
	stack<int> stk;
	for (int i = 0; i < str.size(); i++)
	{
		int t = mp[str[i]];
		if (t < 0) // 右括号
		{
			if (stk.empty() || stk.top() != -t)
				return false;
			else
				stk.pop();
		}
		else // 左括号
		{
			if (stk.size() && t > stk.top())
				return false;
			stk.push(t);
		}
	}
	return stk.empty();
}
int main()
{
	string str;
	cin >> str;

	if (check(str))
		cout << "True" << endl;
	else
		cout << "False" << endl;

	system("pause");
	return 0;
}

编程题 2:LRU缓存

Leetcode146. LRU 缓存

完整的程序:

#include <iostream>
#include <list>
#include <unordered_map>
using namespace std;

class LRUCache
{
private:
    unordered_map<int, list<pair<int, int>>::iterator> hash;
    // 链表的链接顺序即为最近使用的新旧顺序,最新的信息在链表头节点
    list<pair<int, int>> cache;
    int size;

public:
    LRUCache(int capacity) : size(capacity) {}

    int get(int key)
    {
        auto it = hash.find(key);
        if (it == hash.end())
            return -1;
        // 将 it->second 从 cache 剪切到 cache 的开头
        cache.splice(cache.begin(), cache, it->second);
        return it->second->second;
    }

    void put(int key, int value)
    {
        auto it = hash.find(key);
        // 如果关键字 key 已经存在
        if (it != hash.end())
        {
            // 变更其数据值 value
            it->second->second = value;
            // 将 it->second 从 cache 剪切到 cache 的开头
            cache.splice(cache.begin(), cache, it->second);
            return;
        }
        // 向缓存中插入该组 key-value
        cache.insert(cache.begin(), make_pair(key, value));
        hash[key] = cache.begin();
        // 如果插入操作导致关键字数量超过 capacity
        if (cache.size() > size)
        {
            // 逐出最久未使用的关键字
            hash.erase(cache.back().first);
            cache.pop_back();
        }
    }
};

int main()
{
	LRUCache lRUCache = LRUCache(2);
	lRUCache.put(1, 1); // 缓存是 {1=1}
	lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
	cout << lRUCache.get(1) << endl;    // 返回 1
	lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
	cout << lRUCache.get(2) << endl;    // 返回 -1 (未找到)
	lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
	cout << lRUCache.get(1) << endl;    // 返回 -1 (未找到)
	cout << lRUCache.get(3) << endl;    // 返回 3
	cout << lRUCache.get(4) << endl;    // 返回 4
	
	system("pause");
	return 0;
}

参考:

  1. https://blog.csdn.net/weixin_42280274/article/details/109676523

编程题 3:找出数组所有出现两次的元素

Leetcode442. 数组中重复的数据

  • 19
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值