Socket知识点总结-相关面试题(Java)

本文会从两个方面讲起:

  1. 网络结构模型
  2. Socket网络编程

分别总结基础的网络架构知识,延伸Java用Socket实现TCP、UDP编程DEMO(代码可运行)

1. 网络架构模型

1.1 OSI参考模型

Socket知识点总结-相关面试题(Java)
OSI定义了网络互连的七层框架(物理层、数据链路层、网络层、传输层、会话层、表示层、应用层)。

1.2 TCP/IP五层模型

Socket知识点总结-相关面试题(Java)

1.3 各层简述

Socket知识点总结-相关面试题(Java)

  • 应用层
    应用层最靠近用户的一层,是为计算机用户提供应用接口,也为用户直接提供各种网络服务。我们常见应用层的网络服务协议有:HTTP,HTTPS,FTP,TELNET等。

  • 传输层
    建立了主机端到端的链接,传输层的作用是为上层协议提供端到端的可靠和透明的数据传输服务,包括处理差错控制和流量控制等问题。该层向高层屏蔽了下层数据通信的细节,使高层用户看到的只是在两个传输实体间的一条主机到主机的、可由用户控制和设定的、可靠的数据通路。我们通常说的,TCP UDP就是在这一层。端口号既是这里的“端”。

  • 网络层
    本层通过IP寻址来建立两个节点之间的连接,为源端的运输层送来的分组,选择合适的路由和交换节点,正确无误地按照地址传送给目的端的运输层。就是通常说的IP层。这一层就是我们经常说的IP协议层。IP协议是Internet的基础。

1.4 TCP、UPD简述

  • TCP
    TCP是(Tranfer Control Protocol)的简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须建立连接,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作。
  • UDP
    UDP是(User Datagram Protocol)的简称,是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。

2. Socket编程

2.1 什么是socket?

在网络编程中,网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
Socket套接字是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。

2.2 Socket原理

Socket实质上提供了进程通信的端点。进程通信之前,双方首先必须各自创建一个端点,否则是没有办法建立联系并相互通信的。正如打电话之前,双方必须各自拥有一台电话机一样。
套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。

  1. 服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
  2. 客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
  3. 连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

2.3 通信流程

Socket知识点总结-相关面试题(Java)

相关面试题

面试题一

编写一个网络应用程序,有客户端与服务器端,客户端向服务器发送一个字符串,服务器收到该字符串后将其打印到命令行上,然后向客户端返回该字符串的长度,最后,客户端输出服务器端返回的该字符串的长度

下面是TCP实现

package com.soket;


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpDemo {
    public static void main(String[] args) {
        try {
            // 创建一个ServerSocket,监听Client端发来的数据
            ServerSocket serverSocket = new ServerSocket(65000);
            Socket socket = serverSocket.accept();
            new TcpServerThread(socket).run();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class TcpServerThread extends Thread {
    private Socket socket;

    public TcpServerThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            // TCP是有连接的,取出socket对应的输入、输出流
            InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();

            // 读取输入流(client发来的消息)
            int len = 0;
            byte[] bufferArr = new byte[1024];
            len = inputStream.read(bufferArr);
            String content = new String(bufferArr, 0, len);

            // 业务xxx,此处为打印发来的字符串,并计算字符串长度
            System.out.println(content);

            // 将数据封装成byte[],通过输出流传回客户端
            String sendData = new String(String.valueOf(content.length()));
            outputStream.write(sendData.getBytes(),0,sendData.length());
            outputStream.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class TcpClient {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("127.0.0.1", 65000);
            InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();

            byte[] sendData = "服务端你好!".getBytes();
            outputStream.write(sendData,0,sendData.length);
            outputStream.flush();

            int len = 0;
            byte[] bufferArr = new byte[1024];
            len = inputStream.read(bufferArr);
            String content = new String(bufferArr, 0, len);
            System.out.println(content);

        }catch (Exception e){
            e.printStackTrace();
        }

    }
}

UDP实现

package com.soket;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UdpDemo {
    public static void main(String[] args) {
        // 别问我为啥这嘎达啥也不写,问就是就空着玩儿~
    }
}


//服务端代码
class UDPServer {

    public static void main(String[] args) throws Exception {
        // 服务端接受客户端发送的数据报
        DatagramSocket socket = new DatagramSocket(65001); //监听的端口号
        byte[] buff = new byte[100]; //存储从客户端接受到的内容
        DatagramPacket pocket = new DatagramPacket(buff, buff.length);
        //接受客户端发送过来的内容,并将内容封装进DatagramPacket对象中
        socket.receive(pocket);

        byte[] data = pocket.getData(); //从DatagramPacket对象中获取到真正存储的数据
        //将数据从二进制转换成字符串形式
        String content = new String(data, 0, pocket.getLength());
        System.out.println(content);
        //将要发送给客户端的数据转换成二进制
        byte[] sendedContent = String.valueOf(content.length()).getBytes();
        // 服务端给客户端发送数据报
        //从DatagramPacket对象中获取到数据的来源地址与端口号
        DatagramPacket packetToClient = new DatagramPacket(sendedContent,
                sendedContent.length, pocket.getAddress(), pocket.getPort());
        socket.send(packetToClient); //发送数据给客户端
    }
}

//客户端的代码
class UDPClient {

    public static void main(String[] args) throws Exception {
        // 客户端发数据报给服务端
        DatagramSocket socket = new DatagramSocket();
        // 要发送给服务端的数据
        byte[] buf = "Hello World".getBytes();
        // 将IP地址封装成InetAddress对象
        InetAddress address = InetAddress.getByName("127.0.0.1");
        // 将要发送给服务端的数据封装成DatagramPacket对象 需要填写上ip地址与端口号
        DatagramPacket packet = new DatagramPacket(buf, buf.length, address,
                65001);
        // 发送数据给服务端
        socket.send(packet);

        // 客户端接受服务端发送过来的数据报
        byte[] data = new byte[100];
        // 创建DtagramPacket对象用来存储服务端发送过来的数据
        DatagramPacket receivedPacket = new DatagramPacket(data, data.length);
        // 将接受到的数据存储到DatagramPacket对象中
        socket.receive(receivedPacket);
        // 将服务器端发送过来的数据取出来并打印到控制台
        String content = new String(receivedPacket.getData(), 0,
                receivedPacket.getLength());
        System.out.println(content);

    }
}

面试题二:TCP和UDP的区别

UDP:

  1. 每个数据报中都给出了完整的地址信息,因此无需要建立发送方和接收方的连接。
  2. UDP传输数据时是有大小限制的,每个被传输的数据报必须限定在64KB之内。
  3. UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方

TCP:

  1. 面向连接的协议,在socket之间进行数据传输之前必然要建立连接,所以在TCP中需要连接时间。
  2. TCP传输数据没有大小限制,一旦连接建立起来,双方的socket就可以按统一的格式传输大的数据。
  3. TCP是一个可靠的协议,它确保接收方完全正确地获取发送方所发送的全部数据。

应用:

  1. TCP在网络通信上有极强的生命力,例如远程连接(Telnet)和文件传输(FTP)都需要不定长度的数据被可靠地传输。但是可靠的传输是要付出代价的,对数据内容正确性的检验必然占用计算机的处理时间和网络的带宽,因此TCP传输的效率不如UDP高。
  2. UDP操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中client/server应用程序。例如视频会议系统,并不要求音频视频数据绝对的正确,只要保证连贯性就可以了,这种情况下显然使用UDP会更合理一些。

参考

Java的Socket编程
Java的Socket详解

版权声明:程序员胖胖胖虎阿 发表于 2022年10月1日 上午5:40。
转载请注明:Socket知识点总结-相关面试题(Java) | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...