扎人心的腾讯春招实习(一面)


最近两次面试情况都不好,尤其是腾讯。题目大部分都没有答上来,尤其是有些题目并不是很难。但是也有一些很麻烦的题目,一时半会也想不到特别好的解决方案。

接收端:

Q:TCP和UDP区别,在用TCP的时候发现什么问题

Q:用UDP怎么判断数据收到了?

  • 包中增加编号,发送侧将发送过的包序号保存,接收侧将接收到的包的序号返回,发送方按照返回的序号将保存的序号清空,同时使用定时器,一段时间内没有返回的包认为丢失,进行重发。
  • UDT

Q:用UDP无法用多线程怎么办?即UDP的并发处理。

  • UDP并发处理

  • 并发的常见思路是使用多线程。服务器在读取一个新请求之后,可以交由一个线程处理,该线程在处理之后直接将响应内容发给客户端。另一方面,udp服务器和多个客户端交互,但是却没有多个socket。典型的解决方案是,服务器为每个客户端创建一个新的socket,并绑定一个新的端口。客户端以后就通过这个新的socket与服务器通信,获得响应。总结来说,udp并发服务器,针对多个客户端,可以创建多个socket;针对多个请求,可以使用多线程(线程池)进行处理。(我很怀疑这种做法,UDP)

  • 基于asio(他内部是IOCP),在结构上如下实现:
    1)对tcp,accept使用cpu数目个线程进行accept。
    2)对udp以及tcp accept后的线程,使用统一的线程池处理。比如,对udp:这些线程同时投递很多async_recv_from。然后有了IOCP的事件通知后,进行工作处理,处理完成后直接发送,发送完成后再次进入等待async_recv_from。如果中间某个线程处理时,需要读文件或者sleep,此时如果还有其他网络数据需要处理,则自动由其它线程处理。 同时运行的线程数设置是cpu数目,但如果有人sleep,则可以有备选线程进入处理。

  • erlang

  • 如果是在linux平台的话,可以考虑多进程,大概思路:主进程bind一个端口,然后启动子进程,在子进程中完成recvfrom和sendto操作。如果要想提高吞吐量只需增加子进程个数就可以了,单台机器不够可以扩展到多台机器用域名来平衡即可。而且这个结构还有个好处,一个任务占用时间较多的话,只是一个子进程消耗时间,并不会影响其他子进程处理其他业务。

Q: 传输协议是怎么定的?
Q: 系统review,如果在使用UDP协议下判断节点是不是崩了?

  • 网关发心跳包
  • 超时判断
    解决方案
  • 个人感觉这不是一个很好的解决方案,因为iperf是客户端检查和sever有没有断开,而netcat貌似是不具备检查是不是断开的。利用现有的工具
    netcat/iperf
  • netstat查看:netstat |grep 30010查看30010上是不是有连接。测试后,假如是用netcat建立一个udpClient,查看后就是established。如果关闭的话,就没有这一条了。

Q:怎么用shell指令查看连接数?

Q:服务器最多有多少连接?是什么数量级的?1w,10w还是100w?

  • port数(同一IP下)峰值为65535
  • Windows 下为32762,不确定那个面试官问的是不是这个问题。

Q: 数据传的时候是大端模式还是小端模式?网络上是大端还是小端?接收端呢?

大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;

小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。“小端低低”。

在网络上传输数据时,由于数据传输的两端对应不同的硬件平台,采用的存储字节顺序可能不一致。所以在TCP/IP协议规定了在网络上必须采用网络字节顺序,也就是大端模式。对于char型数据只占一个字节,无所谓大端和小端。而对于非char类型数据,必须在数据发送到网络上之前将其转换成大端模式。接收网络数据时按符合接受主机的环境接收。

大小端是由CPU而不是操作系统决定的。

The endian is a property of the CPU not the OS. An operating system can be ported to work on many hardware architectures, which means that an OS can work on different endians. ... Both Windows and the versions of Linux designed for those CPUs (such as Ubuntu and Fedora) have the same endian. 64bit has 4 bits per byte when the most significant bit of 4 bits get the most insignificant address this is big endianess, reversed would be small endianess..

LSB(least significant byte): The MSB in an 8-bit binary number represents a value of 128 decimal. The LSB represents a value of 1. In computing, the least significant bit (LSB) is the bit position in a binary integer giving the units value, that is, determining whether the number is even or odd.

Paste_Image.png

Q: 为什么使用多线程而不是多进程?

  • 多线程和多进程的选择和OS。对于UNIX和Linux,主要首选多进程,Win多线程。
  • 进程比较稳定,但是fork一个进程处理请求往往要将主进程的很多东西 拷贝一份到fork的子进程,所以可能在并发量高的情况下,内存占用比较多
  • 线程则针对高并发的环境

C++

Q: 函数里面的static和普通数据类型有什么区别?存储在哪里?

  • 好奇怪哦,在函数里面的static不用初始化,如果初始化了,只会在函数第一次被调用时出现,下一次运行该程序这个值还是原来定义的那个哦,而不是重新再分配内存
  • 每次函数都会改变值
  • 函数运行次数也可以用这个方法

Q:vector存储在哪里?指针存储在哪里?

  • vetctor数据在堆,指针在栈,指向的元素在堆中

Q:堆和栈有什么区别?堆内存和栈内存有哪些特性?

Q:用STL中队列实现栈,栈实现队列

\\java

import java.util.Stack;
/*题目要求: 用两个栈实现队列
 * 思路:      每次push都push到Stack1中
 *        Pop的时候,先判断Stack2是不是空的,如果不是就Pop这个的
 *                 (上次Stack1 pop出来的没弄完)
 *                 如果是空的话,全部将Stack1 pop出来,push进去(有点像汉罗塔)*/
public class StackToQueue {
     Stack<Integer> stack1 = new Stack<Integer>();
     Stack<Integer> stack2 = new Stack<Integer>();
     public void push(int node) {
            stack1.push(node);
        }
        
        public int pop() {
            if(!stack2.isEmpty())
                return stack2.pop();
            else{
                while(!stack1.isEmpty())
                    stack2.push(stack1.pop());
                    return stack2.pop();
            }
        }
        public static void main(String args[]){
            
            StackToQueue stackQueue=new StackToQueue();
            stackQueue.push(1);
            stackQueue.push(2);
            stackQueue.push(3);
            System.out.println(stackQueue.pop());
            System.out.println(stackQueue.pop());
            stackQueue.push(4);
            System.out.println(stackQueue.pop());
            stackQueue.push(5);
            System.out.println(stackQueue.pop());
            System.out.println(stackQueue.pop());
            
        }
}

\\C++ 用JAVA实现没什么意思,因为JAVA本身的LinkedList等都能删除队尾元素,也能得到队尾元素
\\C++ 队列有一点很烦人,pop时候只能pop不能顺便返回对头的值。
\\pop主要思想返回队列的尾元素,然后把剩下的全部放到另外一个队列中
#include<iostream>
#include<queue>
#include<stack>
using namespace std;

class queueToStack{
    queue<int>q1;
    queue<int>q2;
public:void push(int e){
        q1.push(e);
    }
public:int pop(){
           int elem = 0;
           if (q1.size() == 0 && q2.size() == 0)
               return NULL;
           if (!q1.empty()){
               elem = q1.back();
               while (q1.size() - 1 > 0){
                   q2.push(q1.front());
                   q1.pop();
               }
               q1.pop();
           }
           else{
               elem = q2.back();
               while (q2.size() - 1 > 0){
                   q1.push(q2.front());
                   q2.pop();
               }
               q2.pop();
           }
           return elem;
}
};
void main(){
    queueToStack test;
    test.push(1);
    test.push(5);

    cout << test.pop();
    test.push(3);
    cout << test.pop();
    
}

Q:hashmap和map是怎么实现的。
Q:内存对齐:sizeof相关,以及sizeof是干什么的:

\\No. 1: 结构体
struct node{

int a;
double b;
char c;
};\\Output: 64位系统:24=4+4+8+1+7;32位系统:4+(4+4)+1+3=16```

\No. 2: 类
class node{

int a;
int b;
char c;
};\Output: 4+4+1+3```

\\No. 3: 加上函数的类
class node{

int a;
int b;
char c;
int d(int c);
}\\Output: 不变滴```

\No. 4: 加上虚函数的类
class node{int a;

int b;
char c;
virtual int d(int c);
}\Output: 4+1+3+4```

\\No. 5: 加上自定义的类
class sensor{
char temp[33];
};
class node{int a;
int b;
char c;
}\\Output: 8+8+8+1+7+1+7```

\No. 6: union
union node{int a;
int b;
char c;
}\Output: 4```
sizeof对齐方式
为什么要内存对齐
32位和64位对齐有什么不同
总结如下:

  • 内存对齐:即内存起始地址为它本身占用字节的整数倍,最后整体占用字节数为占用最大字节的变量的整数倍。
  • 不同系统中, 对于64位系统,它有八个字节,而对于32位系统,是4个字节(64位char*为8字节,而32位为4字节,和寻址空间有关)。对于不同位的系统。例如64位node结构体,偏移量为0时存储a变量(4个字节),然后要存储b的时候发现偏移量为4,不是它本身的整数倍,因为给a补4个字节,再加上其本身的8个字节,这时候偏移量为16.然后c来了,16是sizeof(char)=1的整数倍,因此前面不用补。但是这时候这个结构体偏移量为17.不是max(sizeof(var))的整数倍,因此再补7个。但是因为32位系统只有四个字节,所以double是被截成两个4个字节的,所以就不太一样了。
  • 内存对齐是以class中最大的那个基本类型为基准的,如果class中有自定义类型,则递归的取其中最大的基本类型来参与比较。在No.5内存块一个接一个的过来接走数据成员,一直到第5块的时候,BigData里只剩1个char了,将它放入内存块中,内存块还剩7个bytes,接下来是个int(4bytes),能够放下,所以也进入第5个内存块,这时候内存块还剩3bytes,而接下来是个double(8bytes),放不下,所以要等下一个内存快到来。因此,No.5的Data的size=33+4+(3)+8=48(64位)
  • 类的普通成员、静态成员函数是不占类内存的,类中有虚函数的时候存在一个虚函数表指针,会增加4个字节。然后你再添虚函数结果还是一样了。
  • 静态成员不属于类,所以sizeof不到静态成员。
  • union,每次只能存取一个成员,因此就是等于对齐之后最大值。

Q: 函数调用次数统计(程序调用次数?记不清了)

  • 函数外定义static,然后函数内每次递增(这种题都不会了,好搞笑哦)

操作系统

  1. 进程间通信方式
    asdasd
  2. 线程资源共享

其他:
游戏匹配模式设计
滴滴打车的用户如何快速匹配车主?需要用那些数据结构和算法?假如一个1w的用户,存储这些内存要占用多少?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • __block和__weak修饰符的区别其实是挺明显的:1.__block不管是ARC还是MRC模式下都可以使用,...
    LZM轮回阅读 3,282评论 0 6
  • 1.写一个NSString类的实现 +(id)initWithCString:(c*****t char *)nu...
    韩七夏阅读 3,744评论 2 37
  • 史上最全的iOS面试题及答案 iOS面试小贴士———————————————回答好下面的足够了----------...
    Style_伟阅读 2,345评论 0 35
  • iOS面试小贴士 ———————————————回答好下面的足够了------------------------...
    不言不爱阅读 1,960评论 0 7
  • 多线程、特别是NSOperation 和 GCD 的内部原理。运行时机制的原理和运用场景。SDWebImage的原...
    LZM轮回阅读 2,003评论 0 12