网络编程学习----(4)面试常见问题
1 TCP和UDP的区别
TCP:是面向连接的流传输控制协议,具有高可靠性,确保传输数据的正确性,有验证重发机制,因此不会出现丢失或乱序。
UDP:是无连接的数据报服务,不对数据报进行检查与修改,无须等待对方的应答,会出现分组丢失、重复、乱序,但具有较好的实时性,UDP段结构比TCP的段结构简单,因此网络开销也小。
3 多线程如何同步
下面的文章写的非常好
https://blog.csdn.net/u011033906/article/details/53840525
windows:线程同步有四种方式:临界区、内核对象、互斥量、信号量。
Linux:线程同步有最常用的是:互斥锁、条件变量和信号量。
4 进程间通讯(IPC,InterProcess Communication)的方式有哪些,各有什么优缺点?
IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等。其中 Socket和Streams支持不同主机上的两个进程IPC。
(1)管道
管道,通常指无名管道,是 UNIX 系统IPC最古老的形式。
- 它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。
- 它只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)。
- 它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。
(2)FIFO
FIFO,也称为命名管道,它是一种文件类型。
- FIFO可以在无关的进程之间交换数据,与无名管道不同。
- FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中。
(3)消息队列
消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。
- 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
- 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
- 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。
(4)信号量
信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。
- 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
- 信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。
- 每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数。
- 支持信号量组。
(5)共享内存
共享内存(Shared Memory),指两个或多个进程共享一个给定的存储区。
- 共享内存是最快的一种 IPC,因为进程是直接对内存进行存取。
- 因为多个进程可以同时操作,所以需要进行同步。
- 信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。
https://blog.csdn.net/wh_sjc/article/details/70283843
5 epoll与select的区别
select的轮询机制是系统会去查找每个fd是否数据已准备好,当fd很多的时候,效率当然就直线下降了,epoll采用基于事件的通知方式,一旦某个fd数据就绪时,内核会采用类似callback的回调机制,迅速激活这个文件描述符,而不需要不断的去轮询查找就绪的描述符,这就是epoll高效最本质的原因。
6 connect方法会阻塞,请问有什么方法可以避免其长时间阻塞?
最通常的方法最有效的是加定时器;也可以采用非阻塞模式。也可以考虑采用异步传输机制,同步传输与异步传输的主要区别在于同步传输中,如果调用recvfrom后会一致阻塞运行,从而导致调用线程暂停运行;异步传输机制则不然,会立即返回。
7 路由表示做什么用的?在linux环境中怎么来配置一条默认路由?
路由表是用来决定如何将包从一个子网传送到另一个子网的,换句话说就是用来决定从一个网卡接收到的包应该送的哪一张网卡上的。在Linux上可以用“route add default gw <默认路由器IP>”来配置一条默认路由。
8 在网络中有两台主机A和B,并通过路由器和其他交换设备连接起来,已经确认物理连接正确无误,怎么来测试这两台机器是否连通?如果不通,怎么来判断故障点?怎么排除故障?
测试这两台机器是否连通:从一台机器ping另一台机器。如果ping不通,用traceroute可以确定是哪个路由器不能连通,然后再找问题是在交换设备/hup/cable等。
9 网络编程中设计并发服务器,使用多进程与多线程 ,请问有什么区别?
- 进程:子进程是父进程的复制品。子进程获得父进程数据空间、堆和栈的复制品。
- 线程:相对与进程而言,线程是一个更加接近与执行体的概念,它可以与同进程的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。
- 两者都可以提高程序的并发度,提高程序运行效率和响应时间。
- 线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。
- 根本区别就一点:多进程每个进程有自己的地址空间(address space),线程则共享地址空间。所有其它区别都是由此而来的:
10 网络编程的一般步骤?
(1)TCP连接
1.服务器端
- 1)创建套接字create;
- 2)绑定端口号bind;
- 3)监听连接listen;
- 4)接受连接请求accept,并返回新的套接字;
- 5)用新返回的套接字recv/send;
- 6)关闭套接字。
Server端:create – bind – listen– accept– recv/send– close
2.客户端
- 1)创建套接字create;
- 2)发起建立连接请求connect;
- 3)发送/接收数据send/recv;
- 4)关闭套接字。
Client端:create——- conncet——send/recv——close.
(2)UDP连接
1 服务器端
- 1)创建套接字create;
- 2)绑定端口号bind;
- 3)接收/发送消息recvfrom/sendto;
- 4)关闭套接字。
Server端:create—-bind —-recvfrom/sendto—-close
2 客户端
- 1)创建套接字create;
- 2)发送/接收消息sendto/recvfrom;
- 3)关闭套接字.
Client端:create—- sendto/recvfrom—-close
11 网络编程时的同步、异步、阻塞、非阻塞?
- 同步:函数调用在没得到结果之前,没有调用结果,不返回任何结果。
- 异步:函数调用在没得到结果之前,没有调用结果,返回状态信息。
- 阻塞:函数调用在没得到结果之前,当前线程挂起。得到结果后才返回。
- 非阻塞:函数调用在没得到结果之前,当前线程不会挂起,立即返回结果。
12 Java如何实现无阻塞方式的Socket编程?
NIO有效解决了多线程服务器存在的线程开销问题。在NIO中使用多线程主要目的不是为了应对每个客户端请求而分配独立的服务线程,而是通过多线程充分利用多个CPU的处理能力和处理中的等待时间,达到提高服务能力的目的。
13 什么是java 的序列化(串行化)?
简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。
14 什么情况下需要序列化?序列化的注意事项,如何实现java 序列化(串行化)?
- 希望把的内存中的对象状态保存到一个文件中或者数据库中时候;
- 希望用套接字在网络上传送对象的时候;
- 希望通过RMI传输对象的时候;
15 网络模型:OSI参考模型、TCP/IP参考模型、网络通讯要素
16 常见四大异常
(1)第1个异常是 java.net.BindException:Address already in use: JVM_Bind
该异常发生在服务器端进行new ServerSocket(port)(port是一个0,65536的整型值)操作时。异常的原因是以为与port一样的一个端口已经被启动,并进行监听。
(2)第2个异常是java.net.SocketException: Connection refused: connect
该异常发生在客户端进行 new Socket(ip, port)操作时,该异常发生的原因是或者具有ip地址的机器不能找到(也就是说从当前机器不存在到指定ip路由),或者是该ip存在,但找不到指定的端口进行监听。
(3)第3个异常是java.net.SocketException: Socket is closed
该异常在客户端和服务器均可能发生。异常的原因是己方主动关闭了连接后(调用了Socket的close方法)再对网络连接进行读写操作。
(4)第4个异常是java.net.SocketException: (Connection reset或者Connect reset by peer:Socket write error)
该异常在客户端和服务器端均有可能发生,引起该异常的原因有两个,第一个就是如果一端的Socket被关闭(或主动关闭或者因为异常退出而引起的关闭),另一端仍发送数据,发送的第一个数据包引发该异常(Connect reset by peer)。另一个是一端退出,但退出时并未关闭该连接,另一端如果在从连接中读数据则抛出该异常(Connection reset)。简单的说就是在连接断开后的读和写操作引起的。
(5)第5个异常是java.net.SocketException: Broken pipe
该异常在客户端和服务器均有可能发生。在第4个异常的第一种情况中(也就是抛出 SocketExcepton:Connect reset by peer:Socket write error后),如果再继续写数据则抛出该异常。前两个异常的解决方法是首先确保程序退出前关闭所有的网络连接,其次是要检测对方的关闭连接操作,发现对方关闭连接后自己也要关闭该连接。
END