IO流,多线程,网络编程等相关面试题

目录

 

IO流

1.Java中有几种类型的流?

2.字节流和字符流哪个好?怎么选择?

3.字节流和字符流有什么区别?

4.Java IO与 NIO的区别?

5.什么是Java序列化,如何实现Java序列化?

6.什么是节点流,什么是处理流,它们各有什么用处,处理流的创建有什么特征?

7.你知道阻塞 IO 模型吗?

8.异步 IO 模型?

9. 你能将PrintStream、BufferedWriter、PrintWriter做比较吗?

10. BufferedReader属于哪种流,它主要是用来做什么的,它里面有那些经典的方法?

11.InputStream里的read()返回的是什么,read(byte[] data)是什么意思,返回的是什么值?

12.OutputStream里面的write()是什么意思,write(byte b[], int off, int len)这个方法里面的三个参数分别是什么意思?

13.什么是比特(Bit),什么是字节(Byte),什么是字符(Char),它们长度是多少,各有什么区别?

14.如果我要打印出不同类型的数据到数据源,那么最适合的流是那个流,为什么?

15.怎么样把输出字节流转换成输出字符流,说出它的步骤?

16.谈一谈io流中用到的适配器模式和装饰者模式?

多线程

1.线程创建4种方式?

2.为什么要使用线程池?

3.线程池的构造方法里几个参数的作用分别都是什么?

4.什么是线程安全问题?如何解决线程安全问题?

5.谈一谈线程生命周期(状态)?

6.notify()和 notifyAll()有什么区别?

7.sleep()和wait() 有什么区别?

8.谈谈JAVA的后台线程?

9.你都知道哪些线程相关的基本方法?

10.什么是线程?

11.什么是自旋锁?

12. Java中的volatile 变量是什么?

13.有三个线程T1,T2,T3,怎么确保它们按顺序执行?

网络编程

1、TCP和UDP的区别 ?

2.tcp连接建立的时候3次握手,断开连接的4次握手的具体过程?

3.socket是什么?

4.为什么需要端口?端口是真实存在的还是虚拟的概念? 

5.URL类有什么作用?

6.基于TCP的Socket网络编程的主要步骤是什么?

7.简单说一下http协议?

8.http协议下客户端请求报文的格式?http协议服务器响应报文的格式?

9.常见的HTTP状态码有哪些?

10.网络传输协议本质和作用是什么?


IO流

1.Java中有几种类型的流?

答:1. 按照流的流向分,可以分为 输入流和输出流 ;      2. 按照操作单元划分,可以划分为 字节流和字符流 ;       3. 按照流的角色划分为 节点流和处理流
                       

2.字节流和字符流哪个好?怎么选择?

答:    1. 大多数情况下使用字节流会更好,因为大多数时候 IO 操作都是直接操作磁盘文件,所以这些流在传输时都是以字节的方式进行的(图片等都是按字节存储的)

            2.如果对于操作需要通过 IO 在内存中频繁处理字符串的情况使用字符流会好些,因为字符流具备缓冲区,提高了性能

3.字节流和字符流有什么区别?

答:1.以字节为单位输入输出数据,字节流按照8位传输 。以字符为单位输入输出数据,字符流按照16位传输

       2.字节流的操作不会经过缓冲区(内存)而是直接操作文本本身的,而字符流的操作会先经过缓冲区(内存)然后通过缓冲区再操作文件

4.Java IO NIO的区别?

答:NIO即New IO,这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但实现方式不同NIO 主要用到的是块,所以NIO的效率要比IO高很多。在Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。

5.什么是Java序列化,如何实现Java序列化?

答:  序列化就是一种用来处理对象流的机制,将对象的内容进行流化。可以对流化后的对象进行读写操作,可以将流化后的对象传输于网络之间序列化是为了解决在对象流读写操作时所引发的问题

        序列化的实现:将需要被序列化的类实现Serialize接口,没有需要实现的方法,此接口只是为了标注对象可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,再使用ObjectOutputStream对象的write(Object obj)方法就可以将参数obj的对象写出

6.什么是节点流,什么是处理流,它们各有什么用处,处理流的创建有什么特征?

答:  1.节点流: 直接与数据源相连,用于输入或者输出      2.处理流:在节点流的基础上对之进行加工,进行一些功能的扩展      3.特征:处理流的构造器必须要传入节点流的子类

7.你知道阻塞 IO 模型吗?

  答:最传统的一种 IO 模型,即在 读写数据过程中会发生阻塞现象 。当用户线程发出 IO 请求之后,内核会去查看数据是否就绪,如果没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态,用户线程交出CPU 。当数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用 户线程才解除 block 状态。典型的阻塞 IO 模型的例子为: data = socket.read(); 如果数据没有就绪,就会一直阻塞在 read 方法。

8.异步 IO 模型?

答:在异步 IO 模型中,当用户线程发起 read 操作之后,立刻就可以开始去做其它的事。而另一方面,从内核的角度,当它受到一个 asynchronous read 之后,它会立刻返回,说明 read 请求已经成功发起了,因此不会对用户线程产生任何block。然后,内核会等待数据准备完成,然后将数据拷贝到用户线程,当这一切都完成之后,内核会给用户线程发送一个信号,告诉它 read 操作完成了。也就说用户线程完全不需要实际的整个 IO 操作是如何进行的, 只需要先发起一个请求,当接收内核返回的成功信号时表示 IO 操作已经完成,可以直接去使用数据了。

9. 你能将PrintStream、BufferedWriter、PrintWriter做比较吗?

答    1.PrintStream类的输出功能非常强大,通常如果需要输出文本内容,都应该将输出流包装成PrintStream后进行输出。它还提供其他两项功能。与其他输出流不同,PrintStream 永远不会抛出 IOException;而是,异常情况仅设置可通过 checkError 方法测试的内部标志。另外,为了自动刷新,可以创建一个 PrintStream

       2.BufferedWriter:将文本写入字符输出流,缓冲各个字符从而提供单个字符,数组和字符串的高效写入。通过write()方法可以将获取到的字符输出,然后通过newLine()进行换行操作。BufferedWriter中的字符流必须通过调用flush方法才能将其刷出去。并且BufferedWriter只能对字符流进行操作。如果要对字节流操作,则使用BufferedInputStream

       3.PrintWriter的println方法自动添加换行,不会抛异常,若关心异常,需要调用checkError方法看是否有异常发生,PrintWriter构造方法可指定参数,实现自动刷新缓存(autoflush)

10. BufferedReader属于哪种流,它主要是用来做什么的,它里面有那些经典的方法?

答:属于处理流中的缓冲流,可以将读取的内容存在内存里面,有readLine()方法,它,用来读取一行。

11.InputStream里的read()返回的是什么,read(byte[] data)是什么意思,返回的是什么值?

答:返回的是所读取的字节的int型(范围0-255) 。read(byte [ ] data)将读取的字节储存在这个数组。返回的就是传入数组参数的个数

12.OutputStream里面的write()是什么意思,write(byte b[], int off, int len)这个方法里面的三个参数分别是什么意思?

答:1.write将指定字节传入数据源      2.Byte b[ ]是byte数组        3.b[off]是传入的第一个字符、b[off+len-1]是传入的最后的一个字符 、len是实际长度.

13.什么是比特(Bit),什么是字节(Byte),什么是字符(Char),它们长度是多少,各有什么区别?

答:Bit是最小的传输单位,byte是最小的存储单位,1byte=8bit,char 是一种基本数据类型,1char=2byte.

14.如果我要打印出不同类型的数据到数据源,那么最适合的流是那个流,为什么?

答:  要考虑到打印的问题,就要用到打印输出流(printstream:操作字节流;或者是PrintWriter操作字符流)

printstream,因为只有字节流才能读写各种类型的数据

15.怎么样把输出字节流转换成输出字符流,说出它的步骤?

答:    把字节流转成字符流,这里肯定就要用到适配器模式,很自然的要想到outputstreamwriter。它继承了Writer接口,但要创建它必须在构造函数中传入一个outputstream的实例,outputstreamwriter的作用也就是将outputstream适配到Writer。它实现了Reader接口,并且持有了InputStream的引用。(关于适配器的作用,可以想一下电脑转接头的例子)。

           利用转换流outputstreamwriter.创建一个字节流对象,将其作为参数传入转换流outputstreamwriter中,得到字符流对象。

16.谈一谈io流中用到的适配器模式和装饰者模式?

答:装饰器模式:就是动态地给一个对象添加一些额外的职责(对于原有功能的扩展)。

        1.它必须持有一个被装饰的对象(作为成员变量)。

        2.它必须拥有与被装饰对象相同的接口(多态调用、扩展需要)。

       3.它可以给被装饰对象添加额外的功能。

      比如,在io流中,FilterInputStream类就是装饰角色,它实现了InputStream类的所有接口,并持有InputStream的对象实例的引用,BufferedInputStream是具体的装饰器实现者,这个装饰器类的作用就是使得InputStream读取的数据保存在内存中,而提高读取的性能。

       适配器模式:将一个类的接口转换成客户期望的另一个接口,让原本不兼容的接口可以合作无间。

       1.适配器对象实现原有接口

       2.适配器对象组合一个实现新接口的对象

       3.对适配器原有接口方法的调用被委托给新接口的实例的特定方法(重写旧接口方法来调用新接口功能。)

          比如,在io流中, InputStreamReader类继承了Reader接口,但要创建它必须在构造函数中传入一个InputStream的实例,InputStreamReader的作用也就是将InputStream适配到Reader。 InputStreamReader实现了Reader接口,并且持有了InputStream的引用。这里,适配器就是InputStreamReader类,而源角色就是InputStream代表的实例对象,目标接口就是Reader类。

适配器模式主要在于将一个接口转变成另一个接口,它的目的是通过改变接口来达到重复使用的目的;而装饰器模式不是要改变被装饰对象的接口,而是保持原有的接口,但是增强原有对象的功能,或改变原有对象的方法而提高性能。

多线程

1.线程创建4种方式?


                 答:1)继承Thread类创建线程   

                          定义Thread类的子类,并重写该类的run()方法,该方法的方法体就是线程需要完成的任务,run()方法也称为线程执行体。

                          创建Thread子类的实例,也就是创建了线程对象

                          启动线程,即调用线程的start()方法

                         2)实现Runnable接口创建线程

                        定义Runnable接口的实现类,一样要重写run()方法,这个run()方法和Thread中的run()方法一样是线程的执行体

                        创建Runnable实现类的实例,并用这个实例作为Thread的target来创建Thread对象,这个Thread对象才是真正的线程对象

                        第三步依然是通过调用线程对象的start()方法来启动线程

                        3)使用Callable和Future创建线程     

                       创建Callable接口的实现类,并实现call()方法,然后创建该实现类的实例(从java8开始可以直接使用Lambda表达式创建Callable对象)

                       使用FutureTask类来包装Callable对象,该FutureTask对象封装了Callable对象的call()方法的返回值

                       使用FutureTask对象作为Thread对象的target创建并启动线程(因为FutureTask实现了Runnable接口)

                       调用FutureTask对象的get()方法来获得子线程执行结束后的返回值

                      4)使用线程池例如用Executor框架创建

2.为什么要使用线程池?


                   答:线程和数据库连接这些资源都是非常宝贵的资源。那么每次需要的时候创建,不需要的时候销毁,是非常浪费资源的。那么我们就可以使用缓存的策略,也就是使用线程池

                    第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

                    第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。

                    第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控

3.线程池的构造方法里几个参数的作用分别都是什么?


                    答:corePollSize核心线程数。在创建了线程池后,线程中没有任何线程,等到有任务到来时才创建线程去执行任务。

                          maximumPoolSize最大线程数。表明线程中最多能够创建的线程数量。

                          keepAliveTime空闲的线程保留的时间

                          TimeUnit:空闲线程的保留时间单位。

                          BlockingQueue阻塞队列,存储等待执行的任务。参数有ArrayBlockingQueue、  LinkedBlockingQueue、SynchronousQueue可选。

                          ThreadFactory线程工厂,用来创建线程

                          RejectedExecutionHandler:队列已满,而且任务量大于最大线程的异常处理策略

                               ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。

                               ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。

                               ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)

                               ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

4.什么是线程安全问题?如何解决线程安全问题?


                            答:线程安全就是说多线程访问同一代码,不会产生不确定的结果

                                   那么线程安全问题就是当多个线程同时共享,同一个全局变量或者静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。多线程操作共享资源时,导致共享资源出现错乱。线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

                                   解决线程安全问题:线程同步:**即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态。Java中提供了同步机制(synchronized)来解决;同步代码块;同步方法;锁机制

5.谈一谈线程生命周期(状态)?


                            答:当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。在线程的生命周期中,它要经过新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)5 种状态。尤其是当线程启动以后,它不可能一直"霸占"着 CPU 独自运行,所以 CPU 需要在多条线程之间切换,于是线程状态也会多次运行、阻塞之间切换

                       新建状态(NEW):当程序使用 new 关键字创建了一个线程之后,该线程就处于新建状态,此时仅由 JVM 为其分配内存,并初始化其成员变量的值

                       就绪状态(RUNNABLE):当线程对象调用了 start()方法之后,该线程处于就绪状态。 Java 虚拟机会为其创建方法调用栈和程序计数器,等待调度运行。

                       运行状态(RUNNING):如果处于就绪状态的线程获得了 CPU,开始执行 run()方法的线程执行体,则该线程处于运行状态。

                       阻塞状态(BLOCKED):阻塞状态是指线程因为某种原因放弃了 cpu 使用权,也即让出了 cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得 cpu timeslice 转到运行(running)状态。阻塞的情况分三种: 等待阻塞(o.wait->等待对列) :运行(running)的线程执行 o.wait()方法, JVM 会把该线程放入等待队列(waitting queue)中。 同步阻塞(lock->锁池) :运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则 JVM 会把该线程放入锁池(lock pool)中。其他阻塞(sleep/join) :运行(running)的线程执行 Thread.sleep(long ms)或 t.join()方法,或者发出了 I/O 请求时,JVM 会把该线程置为阻塞状态。当 sleep()状态超时、 join()等待线程终止或者超时、或者 I/O处理完毕时,线程重新转入可运行(runnable)状态。

                        线程死亡(DEAD):线程会以下面三种方式结束,结束后就是死亡状态。 正常结束 :1. run()或 call()方法执行完成,线程正常结束。异常结束 :2. 线程抛出一个未捕获的 Exception 或 Error。调用 stop :3. 直接调用该线程的 stop()方法来结束该线程—该方法通常容易导致死锁,不推荐使用。

6.notify()和 notifyAll()有什么区别?

                     答: 1.notify可能会导致死锁,而notifyAll则不会 ;

                             2.任何时候只有一个线程可以获得锁,也就是说只有一个线程可以运行synchronized 中的代码

使用notifyall,可以唤醒所有处于wait状态的线程 ,使其重新进入锁的争夺队列中,而 notify只能唤醒一个
                             3. wait() 应配合 while 循环使用,不应使用 if ,务必在 wait() 调用前后都检查条件,如果不满足,必须调用
notify() 唤醒另外的线程来处理,自己继续 wait() 直至条件满足再往下执行。
 
                             4. notify() 是对notifyAll()的一个优化,但它有很精确的应用场景,并且要求正确使用 。不然可能导致死 锁。正确的场景应该是 WaitSet 中等待的是相同的条件,唤醒任一个都能正确处理接下来的事项,如果 唤醒的线程无法正确处理,务必确保继续 notify() 下一个线程,并且自身需要重新回到 WaitSet 中。

7.sleep()和wait() 有什么区别?


                     答:1. 对于 sleep()方法,我们首先要知道该方法是属于 Thread 类中的。而 wait()方法,则是属于

Object 类 中的。
                            2. sleep()方法导致了程序暂停执行指定的时间,让出 cpu 该其他线程 ,但是他的监控状态依然 保持者,当指定的时间到了又会自动恢复运行状态
                            3.在调用 sleep() 方法的过程中, 线程不会释放对象锁
                            4. 而当调用 wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用 notify()方法后本线程才进入对象锁定池 准备获取对象锁进入运行状态。


8.谈谈JAVA的后台线程?


                      答:1.后台线程也叫守护线程--也称“服务线程”,它有一个特性,即为用户线程 提供 公共服务, 在没有用户线程可服务时会自动离开。

                             2.优先级:守护线程的优先级比较低,用于为系统中的其它对象和线程提供服务。

                             3. 设置:通过 setDaemon(true)来设置线程为“守护线程”;将一个用户线程设置为守护线程的方式是在 线程对象创建 之前 用线程对象的 setDaemon 方法。在 Daemon 线程中产生的新线程也是 Daemon 的。

                              4.线程则是 JVM 级别的,以 Tomcat 为例,如果你在 Web 应用中启动一个线程,这个线程的生命周期并不会和 Web 应用程序保持同步。也就是说,即使你停止了 Web 应用,这个线程依旧是活跃的。垃圾回收线程就是一个经典的守护线程,当我们的程序中不再有任何运行的Thread, 程序就不会再产生垃圾,垃圾回收器也就无事可做, 所以当垃圾回收线程是 JVM 上仅剩的线程时,垃圾回收线程会自动离开。它始终在低级别的状态中运行,用于实时监控和管理系统中的可回收资源。

                              5.生命周期:守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。也就是说守护线程不依赖于终端,但是依赖于系统,与系统“同生共死”。当 JVM 中所有的线程都是守护线程的时候, JVM 就可以退出了;如果还有一个或以上的非守护线程则 JVM 不会退出。

9.你都知道哪些线程相关的基本方法?


                          答:有 wait, notify, notifyAll, sleep, join, yield 等

                          线程等待(wait):调用该方法的线程进入 WAITING 状态,只有等待另外线程的通知或被中断才会返回,需要注意的是调用 wait()方法后, 会释放对象的锁。因此, wait 方法一般用在同步方法或同步代码块中。

                          线程睡眠(sleep):sleep 导致当前线程休眠,与 wait 方法不同的是 sleep 不会释放当前占有的锁,sleep(long)会导致线程进入 TIMED-WATING 状态,而 wait()方法会导致当前线程进入 WATING 状态

                           线程让步(yield):yield 会使当前线程让出 CPU 执行时间片,与其他线程一起重新竞争 CPU 时间片。一般情况下, 优先级高的线程有更大的可能性成功竞争得到 CPU 时间片, 但这又不是绝对的,有的操作系统对线程优先级并不敏感。

                           线程中断(interrupt) :中断一个线程,其本意是给这个线程一个通知信号,会影响这个线程内部的一个中断标识位。 这个线程本身并不会因此而改变状态(如阻塞,终止等)。

                           等待其他线程终止(join):join() 方法,等待其他线程终止,在当前线程中调用一个线程的 join() 方法,则当前线程转为阻塞 状态,回到另一个线程结束,当前线程再由阻塞状态变为就绪状态,等待 cpu 的宠幸。很多情况下,主线程生成并启动了子线程,需要用到子线程返回的结果,也就是需要主线程需要 在子线程结束后再结束,这时候就要用到 join() 方法 。

                            线程唤醒(notify) :Object 类中的 notify() 方法, 唤醒在此对象监视器上等待的单个线程,如果所有线程都在此对象上等待,则会选择唤醒其中一个线程,选择是任意的,并在对实现做出决定时发生,线程通过调用其中一个 wait() 方法,在对象的监视器上等待, 直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程,被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争。类似的方法还有 notifyAll() ,唤醒再次监视器上等待的所有线程。

10.什么是线程?

  答:线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位,可以使用多线程对进行运算提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒

11.什么是自旋锁?

   答:1.自旋锁原理非常简单, 如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态,它们只需要等一等(自旋),等持有锁的线程释放锁后即可立即获取锁,这样就避免用户线程和内核的切换的消耗。

           2.线程自旋是需要消耗 cup 的,说白了就是让 cup 在做无用功,如果一直获取不到锁,那线程也不能一直占用 cup 自旋做无用功,所以需要设定一个自旋等待的最大时间。

           3.如果持有锁的线程执行的时间超过自旋等待的最大时间扔没有释放锁,就会导致其它争用锁的线程在最大等待时间内还是获取不到锁,这时争用线程会停止自旋进入阻塞状态。

12. Java中的volatile 变量是什么?

    答:volatile是一个特殊的修饰符,只有成员变量才能使用它。保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

13.有三个线程T1,T2,T3,怎么确保它们按顺序执行?

  答:在多线程中有多种方法让线程按特定顺序执行,你可以用线程类的join()方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。为了确保三个线程的顺序你应该先启动最后一个(T3调用T2,T2调用T1),这样T1就会先完成而T3最后完成。

网络编程

1、TCP和UDP的区别 ?

答:1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接

       2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付

       3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的 UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)

       4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信

       5、TCP首部开销20字节;UDP的首部开销小,只有8个字节

       6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道


2.tcp连接建立的时候3次握手,断开连接的4次握手的具体过程?

  答: 

  1. 建立连接采用的3次握手协议,具体是指:

                l 第一次握手是客户端connect连接到server

                l 第二次服务端接受客户端的请求之后,向客户端发送一个消息,相当于说我都准备好了,你连接上我了

                l 第三次 就是client向server发送的,就是对第二次握手消息的确认。之后client和server就开始通讯了。

    2.断开连接的4次挥手,具体如下:

            l 断开连接的一端发送close请求是第一次挥手

            l 另外一端接收到断开连接的请求之后需要对close进行确认,发送一个消息,这是第二次挥手

            l 发送了确认消息之后还要向对端发送close消息,要关闭对对端的连接,这是第3次挥手

            l 而在最初发送断开连接的一端接收到消息之后,进入到一个很重要的状态time_wait状态,这个状态也是面试官经常问道的问题,最后一次握手是最初发送断开连接的一端接收到消息之后。对消息的确认

3.socket是什么?

 答:  1.可以看作用户进程和内核网络协议栈编程(交互)接口

          2.不仅可以在同一台主机上进行通信,也可以在网络上不同的主机间进行通信,也可以异构(软硬件平台不同)进行通信(手机qq和PC机上的qq进行通信,手机的系统是ARM,而PC机是x86)

4.为什么需要端口?端口是真实存在的还是虚拟的概念? 

 答:IP地址用来标志一台计算机,但是一台计算机上可能提供多种网络应用程序,使用端口来区分这些应用程序端口是虚拟的概念,并不是说在主机上真的有若干个端口。通过端口,可以在一个主机上运行多个网络应用程序。端口范围0---65535,16位整数。

5.URL类有什么作用?

  答:  URL:Uniform Resource Locator,统一资源定位器;俗称“网址”,如:"http://www.baidu.com:80/index.html#aa?cansu=bjsxt“   由4部分组成:

            l 协议: http;

            l 存放资源的主机域名:www.baidu.com;

            l 端口号:80;

            l 资源文件名: index.html#aa?cansu=bjsxt;

6.基于TCP的Socket网络编程的主要步骤是什么?

答:基于TCP协议的Socket编程的主要步骤

          服务器端(server):

            1. 构建一个ServerSocket实例,指定本地的端口。这个socket就是用来监听指定端口的连接请求的。

            2.重复如下几个步骤:

            a. 调用socket的accept()方法来获得下面客户端的连接请求。通过accept()方法返回的socket实例,建立了一个和客户端的新连接。

            b.通过这个返回的socket实例获取InputStream和OutputStream,可以通过这两个stream来分别读和写数据。

            c.结束的时候调用socket实例的close()方法关闭socket连接。

          客户端(client):

          1.构建Socket实例,通过指定的远程服务器地址和端口来建立连接。

          2.通过Socket实例包含的InputStream和OutputStream来进行数据的读写。

          3.操作结束后调用socket实例的close方法,关闭。

7.简单说一下http协议?

  答:HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。

HTTP 工作原理

HTTP协议工作于客户端-服务端架构上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。

Web服务器有:Apache服务器,Nginx,IIS服务器(Internet Information Services)等。

Web服务器根据接收到的请求后,向客户端发送响应信息。

HTTP默认端口号为80,但是你也可以改为8080或者其他端口。

HTTP三点注意事项:

l HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

l HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。

l HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

8.http协议下客户端请求报文的格式?http协议服务器响应报文的格式?

 答:请求报文格式由请求行(request line),请求头部(header),请求空行,请求数据四个部分组成。

                 

            响应报文格式由,状态行,消息报头,空行,响应正文四部分组成

9.常见的HTTP状态码有哪些?

   答:

           

例:   200      请求成功。一般用于GET与POST请求;        301      永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI;

          305      使用代理。所请求的资源必须通过代理访问;  400     客户端请求的语法错误,服务器无法理解;

          401       请求要求用户的身份认证                                 403    服务器理解请求客户端的请求,但是拒绝执行此请求;

          404       服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面

          405       客户端请求中的方法被禁止                             500      服务器内部错误,无法完成请求

          501       服务器不支持请求的功能,无法完成请求        505     服务器不支持请求的HTTP协议的版本,无法完成处理

10.网络传输协议本质和作用是什么?

 答:协议本质是双方约定好的一种传输规则,为了让传输数据的双方节点能建立连接,按照约定去传输和解析数据

                 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值