网络编程(JavaEE初阶系列10)

这篇具有很好参考价值的文章主要介绍了网络编程(JavaEE初阶系列10)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言:

1.网络编程的基础

1.1为什么需要网络编程

1.2什么是网络编程

1.3网络编程中的基本概念

1.3.1发送端和接收端

1.3.2请求和响应

1.3.3客户端和服务端

2.Socket套接字

2.1概念

2.2分类

3.UDP数据报套接字编程

3.1DataGramSocket API

3.2DatagramPacket API

3.3基于UDP的回显服务器(echo server)

3.4简单的翻译服务器

4.TCP流套接字

4.1ServerSocket API

4.2Socket API

4.3基于TCP的回显程序

5.再谈协议

结束语:


前言:

在上一节中小编主要是与大家分享了一些有关于网络的基础知识,但是里面的细节和基础的编程还没有给大家来交代,这节中小编就给大家俩交代一下有关于网络基础编程方面的一些基础的编程吧,大家赶快跟上小编的步伐一起来往下看吧。如果还没有看小编网络基础知识的部分的同学建议先去看看这篇博文吧:☞http://t.csdn.cn/aj9ov

1.网络编程的基础

1.1为什么需要网络编程

用户在浏览器中,打开在线视频网站,比如抖音短视频其实质是通过网络,获取到网络上的一个视频资源,与本地打开视频文件类似,只是视频文件这个资源的来源是网络,相比本地资源来说,网络提供了更为丰富的网络资源,所谓的网络资源,其实就是在网络中可以获取的各种数据资源,而所有的网络资源,都是通过网络编程来进行数据传输的。

1.2什么是网络编程

网络编程:指网络上的主机,通过不同的进程,以编程的方式实现网络通信(网络数据传输)

当然,我们只要满足进程不同就行,所以即便是同一个主机,只要是不同进程,基于网络来传输数据,也属于网络编程。

1.3网络编程中的基本概念

1.3.1发送端和接收端

在一次网络数据传输时:

  • 发送端:数据的发送方进程,称为发送端。发送端主机即网络通信中的源主机。
  • 接收端:数据的接收方进程,称为接收端。接收端主机即网络通信中的目的主机。
  • 收发端:发送端和接收端两端,也简称Wie收发端。

注意:发送端和接收端只是相对的概念,只是一次网络数据传输产生数据流向后的概念。

1.3.2请求和响应

一般来说,获取一个网络资源,涉及到两次网络数据传输。

  • 第一次:请求数据的发送。
  • 第二次:响应数据的发送。

就像是在餐厅点饭一样,先发起请求:点一份蛋炒饭。餐厅在给一个响应:提供一份蛋炒饭。

1.3.3客户端和服务端

  • 服务端:在常见的网络数据传输的场景下,把提供服务的这一方进程,称为服务端,可以提供对外服务。
  • 客户端:获取服务的一方进程,称为客户端。

对于服务来说,一般是提供:

  • 客户端获取服务资源。
  • 客户端保存资源在服务端。

就像是我们在银行办事:

  • 银行提供存款服务:用户(客户端)保存现金(资源)在银行(服务端)。
  • 银行提供取款服务:用户(客户端)获取服务端资源(银行替用户保管现金)。

2.Socket套接字

2.1概念

Socket套接字是操作系统提供给应用程序的一组用于网络编程的API。他是基于TCP/IP协议的通信的的基本操作单元。

注意:操作系统原生的Socket API是C语言的但是这里我们学习的是Java封装之后的版本。

2.2分类

Socket套接字主要针对传输层协议划分为如下三类:

  • 数据报套接字:使用传输层UDP协议。

UDP,即User Datagram Protocol(用户数据报协议),传输层协议。它的特点是:无连接、不可靠传输、面向数据报、全双工。

  • 流套接字:使用传输层TCP协议。

TCP,即Transmission Control Protocol(传输控制协议),传输层协议。它的特点是:有连接、可靠传输、面向字节流、全双工。

对于字节流来说,可以简单理解为传输的数据是基于IO流的,流式数据的特征就是在IO流没哟关闭的情况下,是无边界的数据,可以多次发送,也可以分开多次接收。

  • 原始套接字:

原始套接字用于自定义传出层协议,用于读写内核没有处理的IP协议数据,这里我们对此不做过多讨论,我们重点是理解和应用前两个。

TCP特点vsUDP特点:

UDP特点 TCP特点
无连接:使用UDP通信双方不需要刻意保存对方的相关信息 有连接:使用TCP通信双方则需要刻意保存对方的相关信息
不可靠传输:消息发了就发了不关注结果 可靠传输:不是说发送之后对方就可以100%能够达到对方,这要求就太高了,只是说尽可能的传输过去。
面向数据报:以UDP数据报为基本单位。 面向字节流:以字节为传输的基本单位,读写方式非常灵活
全双工:一条路径,双向通信 全双工:一条路径,全向通信。

解释:全双工vs半双工。

  • 全双工:是一条路径,全向通信,你可以理解为,一个双向通道的马路。
  • 半双工:是一条路径,只能由一侧向另一侧通信,你可理解为单向通道的马路。

针对上述的TCP协议和UDP协议也给我们提供了两组不同的API。下面我们来一步一步的了解一下。

3.UDP数据报套接字编程

3.1DataGramSocket API

DataGramSocket 是UDP Socket,用于发送和接收UDP数据报,所谓Socket,是一个特殊的文件,是网卡这个硬件设备的抽象表示,你也可以理解为是一个遥控器,想要进行网络通信就需要有socket文件这样的对象,借助这个socket文件对象,才能够间接的操作网卡。

  • 往这个socket对象里写数据,相当于通过网卡发送消息。
  • 从这个socket对象中读数据,相当于通过网卡接收消息。

DatagramSocket的构造方法,可以绑定一个端口号(服务器),也可以不显示指定客户端。

方法签名 方法说明
DatagramSocket() 创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口(一般用于客户端)
DatagramSocket(int port) 创建一个UDP数据报套接字的Socket,绑定到本机指定的端口(一般用于服务端)
  • 服务器这边的socket往往要关联一个具体的端口号。
  • 客户端这边则不需要手动指定,系统会自动分配一个闲置的端口号。

举个例子:

比如现在我开了一家餐厅,要发传单,那么在传单上面我这边可定是要标清楚我的餐厅的具体位置在哪,窗口号是多少,都得事先分配好,此时我开的这家餐馆就相当于是服务器,确定的地址和窗口号就是服务器事先分配好的端口号。那么如果此时客人看到我发的传单就来到我的餐馆吃饭了,那么它点完餐之后,就会随便找一个空着的位置坐下,等饭。此时客人就相当于是客户端,随便找的位置就是系统给随机分配的一个空闲的端口号。

 DatagramSocket方法

方法签名 方法说明
void receive(DatagramPacket p) 从此套接字接收数据报(如果没有接收到数据报,该方法会阻塞等待)
void send(DatagramPacket p) 从此套接字发送数据报(不会阻塞等待,直接发送)
void close() 关闭数据报套接字(释放资源)

注意:

  • DatagramPacket表示一个UDP数据报。
  • 在close的时候,到底啥时候调用close,一定是要socket/文件,确定一定以及肯定不再使用,此时才能调用close。

3.2DatagramPacket API

DatagramPacket是UDPSocket发送和接收的数据报。

DatagramPacket构造方法

方法签名 方法说明
DatagramPacket(byte[] buf, int length) 构造一个DatagramPacket以用来接收数据报,接收的数据保存在字节数组(第一个参数buf)中,接收指定长度(第二个参数length)
DatagramPacket(byte[] buf, int offset, int lenght, SocketAddress address) 构造一个DatagramPacket以用来发送数据报,发送的数据为字节数组(第一个参数buf)中,从0到指定长度(第二个参数length),address指定目的的主机的IP和端口号。

 DatagramPacket方法

方法签名 方法说明
InetAddress getAddress() 从接收的数据报中,获取发送端主机IP地址,或从发送的数据报中,获取接收端主机IP地址。
int getPort() 从接收的数据报中,获取发送端主机的端口号,或从发送的数据报中,获取接收端主机端口号。
byte[] getData() 获取数据报中的数据。

3.3基于UDP的回显服务器(echo server)

介绍了DatagramSocket 和 DatagramPacket API之后,我们基于UDP socket写一个简单的客户端服务器程序。 也就是让客户端发一个请求,在服务器上返回一个一模一样的响应。

首先来明确一点,一个服务器主要做的三个核心的工作:

  1. 读取请求并解析。
  2. 根据请求并计算响应。(代码中省略了)
  3. 把响应返回给客户端。

服务端代码:

package network;
//服务端
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class UdpEchoServer{
    //需要先定义一个Socket对象
    //通过网络通信,必须要使用socket对象
    private DatagramSocket socket = null;
    //绑定一个端口,不一定能成功
    //如果某个端口已经被别的进程占用了,此时这里的绑定操作就会出错。
    //同一个主机上,一个端口,同一个时刻,只能被一个进程绑定

    public UdpEchoServer(int port) throws SocketException {
        //构造socket的同时,指定要关联/绑定的端口。
        socket = new DatagramSocket(port);
    }

    //启动服务器的主逻辑
    public void start() throws IOException {
        System.out.println("服务器启动成功!");
        while (true) {
            //每次循环,要做三件事
            //1.读取请求并解析
            //  构造空饭盒
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
            // 食堂大妈给饭盒里打菜(饭从网卡上来)
            //这里的receive会阻塞等待,等到客户端那边发送数据过来
            socket.receive(requestPacket);
            //为了方便处理这个请求,需要把数据报转换成String
            String request = new String(requestPacket.getData(), 0, requestPacket.getLength());
            //2.根据请求计算响应(此处省略这个步骤)
            String response = process(request);
            //3.把响应结果写回到客户端
            // 根据response 字符串,构造一个DatagramPacket
            // 和请求packet 不同,此处构造响应的时候,需要指定这个包要发给谁,这里调用requestPacket.getSocketAddress()就可以得知了
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), response.getBytes().length,
                    requestPacket.getSocketAddress());
            socket.send(responsePacket);
            //打印一下请求的地址和请求的端口号,以及请求的内容和响应的内容
            System.out.printf("[%s:%d] req: %s, resp: %s\n", requestPacket.getAddress().toString(),
                    requestPacket.getPort(), request, response);
        }
    }


    //这个方法是希望我们根据请求计算响应。
    //由于咱们写的是个回显程序,请求是啥,响应就是啥
    //如果后续写一个别的服务器,不再回显了,而是具有具体的业务了,就可以修改process方法
    //根据需求来重新构造响应
    //之所以单独列成一个方法,就是想让大家知道这个是一个关键的环节。
    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer udpEchoServer = new UdpEchoServer(9090);
        udpEchoServer.start();
    }
}

客户端代码:

package network;
//客户端
import java.io.IOException;
import java.net.*;
import java.util.Scanner;

public class UdpEchoClient {
    private DatagramSocket socket = null;
    private String serverIP;//服务器的地址
    private int serverPort;//服务器的端口

    //客户端启动,需要知道服务器在哪里
    public UdpEchoClient(String serverIP, int serverPort) throws SocketException {
        //对于客户端来说,不需要显示关联空闲的端口
        //不代表没有端口,而是系统自动分配了一个空闲的端口
        socket = new DatagramSocket();
        this.serverIP = serverIP;
        this.serverPort = serverPort;
    }

    public void start() throws IOException {
        //通过这个客户端可以多次和服务器进行交互
        Scanner scanner = new Scanner(System.in);
        while (true) {
            //1.先从控制台,读取一个字符串过来
            //先打印一个提示符,提示用户要输入内容
            System.out.println("->");
            String request = scanner.next();
            //2.把字符串构造成UDP packet,并进行发送
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,
                    InetAddress.getByName(serverIP), serverPort);
            socket.send(requestPacket);
            //3.客户端尝试读取服务器返回的响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(responsePacket);
            //4.把响应数据转换成String显示出来
            String response = new String(responsePacket.getData(), 0, responsePacket.getLength());
            System.out.printf("req: %s, resp: %s\n", request, response);
        }
    }

    public static void main(String[] args) throws IOException {
        UdpEchoClient udpEchoClient = new UdpEchoClient("127.0.0.1", 9090);
        udpEchoClient.start();
    }
}


启动服务器和客户端结果展示:
网络编程(JavaEE初阶系列10),JavaEE初阶,网络

网络编程(JavaEE初阶系列10),JavaEE初阶,网络 

注意:这里一定是先启动服务器,再启动客户端!!!

执行流程如下所示:

网络编程(JavaEE初阶系列10),JavaEE初阶,网络 

网络编程(JavaEE初阶系列10),JavaEE初阶,网络

网络编程(JavaEE初阶系列10),JavaEE初阶,网络

注意:在上述过程中我们是客户端和服务器在同一个主机上,使用的是127这个IP,不同主机则就写实际的IP即可。

在上述通信过程中,站在客户端发送数据的角度:

  • 源IP是:127.0.0.1
  • 源端口是:64982,他是系统自动分配的空闲端口。
  • 目的IP是:127.0.0.1
  • 目的端口是:9090

在上述过程中就有同学好奇了不是说是要使用close来关闭资源的吗?为什么在代码中好像没有看到释放资源这一步,其实对于UdpEchoServer来说,这个socket对象是出了循环就不用了,但是循环结束,意味着start结束,意味着main方法结束,同时意味着进程结束,那么此时进程都结束了所以的资源也就自然释放了,所以就不必显示释放资源了。

3.4简单的翻译服务器

在上述中我们编写的是一个回显服务器,它是没有实际意义的。那么如何写一个提供实在价值的服务器呢?当响应和请求不一样了,响应是根据不同的请求计算得到的,这里就需要我们对上述过程没有写的process方法来进行编写,那么下来我们就具体来实现一下。我们就来编写一个简单的英文单词翻译服务器,请求是一个英文单词,响应是这个单词的中文翻译。

服务端代码展示:

package network;
//词典查询服务端
import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;

//使用继承,是为了复用之前的代码
public class UdpDicServer extends UdpEchoServer{
    private Map<String, String> dict = new HashMap<>();
    public UdpDicServer(int port) throws SocketException {
        super(port);
        dict.put("dog", "小狗");
        dict.put("cat", "小猫");
        dict.put("tiger", "老虎");
        //注意:这里可以无限添加很多个数据
    }
    @Override
    public String process(String request) {
        return dict.getOrDefault(request,"该单词没有查到!");
    }

    public static void main(String[] args) throws IOException {
        UdpDicServer udpDicServer = new UdpDicServer(9090);
        udpDicServer.start();
    }
}


客户端代码展示:

package network;
//客户端
import java.io.IOException;
import java.net.*;
import java.util.Scanner;

public class UdpEchoClient {
    private DatagramSocket socket = null;
    private String serverIP;//服务器的地址
    private int serverPort;//服务器的端口

    //客户端启动,需要知道服务器在哪里
    public UdpEchoClient(String serverIP, int serverPort) throws SocketException {
        //对于客户端来说,不需要显示关联空闲的端口
        //不代表没有端口,而是系统自动分配了一个空闲的端口
        socket = new DatagramSocket();
        this.serverIP = serverIP;
        this.serverPort = serverPort;
    }

    public void start() throws IOException {
        //通过这个客户端可以多次和服务器进行交互
        Scanner scanner = new Scanner(System.in);
        while (true) {
            //1.先从控制台,读取一个字符串过来
            //先打印一个提示符,提示用户要输入内容
            System.out.println("->");
            String request = scanner.next();
            //2.把字符串构造成UDP packet,并进行发送
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,
                    InetAddress.getByName(serverIP), serverPort);
            socket.send(requestPacket);
            //3.客户端尝试读取服务器返回的响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(responsePacket);
            //4.把响应数据转换成String显示出来
            String response = new String(responsePacket.getData(), 0, responsePacket.getLength());
            System.out.printf("req: %s, resp: %s\n", request, response);
        }
    }

    public static void main(String[] args) throws IOException {
        UdpEchoClient udpEchoClient = new UdpEchoClient("127.0.0.1", 9090);
        udpEchoClient.start();
    }
}


运行结果展示:
网络编程(JavaEE初阶系列10),JavaEE初阶,网络

网络编程(JavaEE初阶系列10),JavaEE初阶,网络 

注意:在上述编写服务端代码时我们是直接使用了继承,重写了父类的process方法。这样就减少了我们的工作。

4.TCP流套接字

在TCP中有两个核心的类:

  • ServerSocket:是给服务器使用的。
  • Socket:即会给客户端使用,又会给服务器端使用。

下面我们就来分别看看ServerSocket和Socket的具体使用方法。

4.1ServerSocket API

他是创建服务端使用的API。

SocketSocket构造方法:

方法签名 方法说明
ServerSocket(int port) 创建一个服务流套接字Socket,并绑定到指定端口

SocketSocket方法: 

方法签名 方法说明
Socket accept() 开始监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端Socket对象,并基于该Socket建立与客户端的连接,否则阻塞等待。
void close() 关闭此套接字

这里的accept意思就是接收,在客户端主动向服务器发起连接请求,服务器就得同意一下,但是实际上的这个accept又和我们上述给大家解释的意思不太一样,这里的accept只是在应用层面的接收,实际的TCP连接的接受是在该内核里已经完成了。这个后面在将TCP的时候会给大家交代的。 

4.2Socket API

Socket是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。

不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端的信息,及用来与对方收发数据的。

Socket的构造方法:

方法签名 方法说明
Socket(String host, int port) 创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接。

这里的host和port指的是服务器的IP和端口,TCP是有连接的,在客户端new Socket对象的时候就会尝试和指定IP端口的目标建立连接了。 

Socket的方法:

方法签名 方法说明
InetAddress getInetAddress() 返回套接字所连接的地址
InputStream getInputStream() 返回此套接字的输入流
OutPutStream getOutStream() 返回此套接字的输出流

 InputStream getInputStream()和OutPutStream getOutStream()是字节流,就可以通过上述字节流对象,进行数据传输了。

  • 从 InputStream 这里读数据,就相当于是从网卡接收。
  • 往 OutPutStream 这里写数据,就相当于从网卡发送。

注意:

这个Socket和DatagramSocket定位类似,都是构造的时候指定一个具体的端口,让服务器绑定该端口,但是ServerSocket一定要绑定具体的端口。

4.3基于TCP的回显程序

服务端代码展示 :

package network;
//服务端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TcpEchoServer {
    //serverSocket只有一个,clientSocket会给每一个客户都分配一个
    private ServerSocket severSocket = null;

    public TcpEchoServer(int port) throws IOException {
        severSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        System.out.println("服务器启动成功!");
        while (true) {
            Socket clientSocket = severSocket.accept();
            //如果直接调用,该方法会影响这个循环的二次执行,导致accept不及时了。
            //创建新的线程,用新线程来调用processConnection
            //每次来一个新的客户端都搞一个新的线程即可!
//            Thread t = new Thread(() -> {
//                try {
//                    processConnection(clientSocket);
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            });
//            t.start();

            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        processConnection(clientSocket);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    //读取这个方法来处理一个连接
    //读取请求
    //根据请求计算响应
    //把响应返回给客户端
    private void processConnection(Socket clientSocket) throws IOException {
        System.out.printf("[%s:%d] 客户端上线!\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());
        //使用try()这种写法,()中允许写多个流对象,使用;来分隔
        try(InputStream inputStream = clientSocket.getInputStream();
            OutputStream outputStream = clientSocket.getOutputStream()) {
            //没有这个scanner和printWriter,完全可以,但是代价就是得一个字节一个字节扣,找到哪个是请求结束的标记\n
            //不是不能做,而是代替代码比较麻烦
            //为了简单,把字节流包装成了更方便的字符流
            Scanner scanner = new Scanner(inputStream);
            PrintWriter printWriter = new PrintWriter(outputStream);
            while (true) {
                //1.读取请求
                //采用hasNext判定接下来还有没有数据了,如果对端关闭了连接(客户端关闭连接),此时hasNext就会返回false,循环就结束
                if (!scanner.hasNext()) {
                    //读取的流到了结尾了(对端关闭了)
                    System.out.printf("[%s:%d] 客户端下线了!\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());
                    break;
                }
                //直接使用scanner读取一段字符串
                //next会一直往后读,读到空白符结束(空格、换行、制表符、翻页符...都算空白符)
                //nextLine只是读到换行符结束,所以这里没有使用它
                String request = scanner.next();
                //2.根据请求计算响应
                String response = process(request);
                //3.把响应写回给客户端,不要忘记了,响应也是要带上换行的
                //返回响应的时候要把换行符加回来,方便客户端那边来区分从哪里到哪里是一个完整的响应。
                printWriter.println(response);
                //flush当数据不够大的时候直接进行强制刷新,将缓冲区中的数据发给客户端
                printWriter.flush();
                System.out.printf("[%s:%d] req: %s; resp: %s\n", clientSocket.getInetAddress().toString(), clientSocket.getPort(), request, response);
            }
        }catch (IOException e) {
            e.printStackTrace();
        }finally {
            //clientSocket只是一个连接提供服务的,这个还是要进行关闭的
            clientSocket.close();
        }
    }

    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer tcpEchoServer = new TcpEchoServer(9090);
        tcpEchoServer.start();
    }
}


客户端代码展示:

package network;
//客户端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoClient {
    private Socket socket = null;

    public TcpEchoClient(String serverIP, int port) throws IOException {
        //这个操作相当于让客户端和服务器建立TCP连接
        //这里的连接连上了,服务器的accept就会返回
        socket = new Socket(serverIP, port);
    }

    public void start() throws IOException {
        Scanner scanner = new Scanner(System.in);
        try (InputStream inputStream = socket.getInputStream();
             OutputStream outputStream = socket.getOutputStream()) {
            PrintWriter printWriter = new PrintWriter(outputStream);
            Scanner scannerFromSocket = new Scanner(inputStream);
            while (true) {
                //1.从键盘上读取用户输入的内容
                System.out.println("->");
                String request = scanner.next();
                //2.把读取到的内容构造成请求,发送给服务器
                //注意,这里的发送,是带有换行的。
                printWriter.println(request);
                printWriter.flush();
                //3.从服务器读取响应的内容
                String response = scannerFromSocket.next();
                //4.把响应结果显示到控制台上
                System.out.printf("req: %s; resp: %s\n", request, response);
            }
        }
    }

    public static void main(String[] args) throws IOException {
        TcpEchoClient client = new TcpEchoClient("127.0.0.1", 9090);
        client.start();
    }
}

结果展示:

网络编程(JavaEE初阶系列10),JavaEE初阶,网络

网络编程(JavaEE初阶系列10),JavaEE初阶,网络

执行流程如下所示:

网络编程(JavaEE初阶系列10),JavaEE初阶,网络

网络编程(JavaEE初阶系列10),JavaEE初阶,网络 

那么这里我们只是启动了一个客户端,在实际中不可能是一个服务器只给一个客户端进行服务,那么如何启动多个客户端呢?这里在idea中是默认下只能启动一个的,那么这里我们需要打开idea配置一下。配置过程如下所示:

网络编程(JavaEE初阶系列10),JavaEE初阶,网络 

网络编程(JavaEE初阶系列10),JavaEE初阶,网络 

此时当我们再次点击上述的三角形就可以再次启动另一个客户端了。

网络编程(JavaEE初阶系列10),JavaEE初阶,网络 

网络编程(JavaEE初阶系列10),JavaEE初阶,网络 

5.再谈协议

回顾并理解我们为什需要协议

以上我们实现的UDP和TCP数据传输,除了UDP和TCP之外,程序还存在应用层定义协议,可以想想分别都是什么样的协议格式。

对于客户端及服务端应用程序来说,请求和响应,需要约定一致的数据格式:

  • 客户端发送请求和服务端解析请求和要使用相同的数据格式。
  • 服务端返回响应和客户端解析响应也要使用相同的数据格式。
  • 请求格式和响应格式可以相同,也可以不同。
  • 约定相同的数据格式,主要目的是为了让接收端在解析的时候明确如何解析数据中的各个字段。
  • 可以使用知名协议(广泛使用的协议格式),如果想自己约定数据格式,就属于自定义协议。

结束语:

这节中小编主要是和大家分享了网络编程中的两个重要的编程UDP和TCP,后期小编还会继续出有关于网络方面的知识的,希望这节对大家了解网络有一定帮助,想要学习的同学记得关注小编和小编一起学习吧!如果文章中有任何错误也欢迎各位大佬及时为小编指点迷津(在此小编先谢过各位大佬啦!)文章来源地址https://www.toymoban.com/news/detail-646514.html

到了这里,关于网络编程(JavaEE初阶系列10)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • [JAVAee]网络编程-套接字Socket

    [JAVAee]网络编程-套接字Socket

    目录 基本概念 发送端与接收端 请求与响应 ​编辑客户端与服务器 Socket套接字  分类 数据报套接字 流套接字传输模型   UDP数据报套接字编程 DatagramSocket API DatagramPacket API InetSocketAddress API 示例一: 示例二: TCP流数据报套接字编程 ServerSocket API Socket API 示例一:   网络编程指的

    2024年02月13日
    浏览(70)
  • 初识网络(JavaEE初阶系列9)

    初识网络(JavaEE初阶系列9)

    目录 前言: 1.网络的发展史 1.1独立模式 1.2网络互联 1.3局域网LAN 1.4广域网WAN 2.网络通信基础 2.1IP地址 2.2端口号 3.认识协议 3.1协议分层 3.2分层的作用 3.3TCP/IP五层(或四层)模型 3.4OSI七层模型 3.5网络设备所在分层 4.封装和分用 结束语: 网络的主要发展大体可以分为这四个阶

    2024年02月14日
    浏览(11)
  • 网络原理(JavaEE初阶系列11)

    网络原理(JavaEE初阶系列11)

    目录 前言: 1.网络原理的理解 2.应用层 2.1自定义协议的约定 2.1.1确定要传输的信息 2.1.2确定数据的格式 3.传输层 3.1UDP 3.1.1UDP报文格式 3.2TCP 3.2.1确认应答 3.2.2超时重传 3.2.3连接管理 3.2.3.1三次握手 3.2.3.2四次挥手 3.2.4滑动窗口 3.2.5流量控制 3.2.6拥塞控制 3.2.7延时应答 3.2.8捎带

    2024年02月13日
    浏览(28)
  • JavaEE-网络编程套接字(UDP/TCP)

    JavaEE-网络编程套接字(UDP/TCP)

    下面写一个简单的UDP客户端服务器流程 思路: 对于服务器端:读取请求,并解析– 根据解析出的请求,做出响应(这里是一个回显,)–把响应写回客户端 对于客户端:从控制台读取用户输入的内容–从控制台读取用户输入的内容–从控制台读取用户输入的内容–将其显示在

    2024年02月07日
    浏览(48)
  • 【JavaEE】网络编程之TCP套接字、UDP套接字

    【JavaEE】网络编程之TCP套接字、UDP套接字

    目录 1.网络编程的基本概念 1.1为什么需要网络编程  1.2服务端与用户端 1.3网络编程五元组  1.4套接字的概念 2.UDP套接字编程 2.1UDP套接字的特点  2.2UDP套接字API 2.2.1DatagramSocket类 2.2.2DatagramPacket类  2.2.3基于UDP的回显程序 2.2.4基于UDP的单词查询  3.TCP套接字编程 3.1TCP套接字的特

    2023年04月20日
    浏览(67)
  • 【JavaEE初阶系列】——网络初识—TCP/IP五层网络模型

    【JavaEE初阶系列】——网络初识—TCP/IP五层网络模型

    目录 🚩网络的发展史 🎈局域网LAN  🎈广域网WAN 🚩网络通信基础 🎈IP地址 🎈端口号 🎈协议类型  🎈五元组 🚩协议分层  🎈什么是协议分层 🎈协议分层的好处 🎈OSI七层网络模型 🎈TCP/IP五层网络模型 💻物理层 💻数据链路层 💻网络层 💻传输层  💻应用层 🎈网络

    2024年04月15日
    浏览(11)
  • 【Java EE初阶十五】网络编程TCP/IP协议(二)

    【Java EE初阶十五】网络编程TCP/IP协议(二)

            tcp的socket api和U大片的socket api差异很大,但是和前面所讲的文件操作很密切的联系         下面主要讲解两个关键的类:         1、ServerSocket:给服务器使用的类,使用这个类来绑定端口号         2、Socket:即会给服务器使用,又会给客户端使用;         

    2024年02月20日
    浏览(17)
  • 【网络编程系列】网络编程实战

    【网络编程系列】网络编程实战

    💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学习,不断总结,共同进步,活到老学到老 导航 檀越剑指大厂系列:全面总

    2024年02月10日
    浏览(12)
  • JavaEE & UDP简易翻译服务器 & 网络编程示例2 & TCP回显服务器,回显客户端

    JavaEE & UDP简易翻译服务器 & 网络编程示例2 & TCP回显服务器,回显客户端

    禁止白嫖 T T 点点赞呗 这个翻译器主要是在上一章的回显服务器和回显客户端上进行修改 修改了计算响应的过程, 即process方法 1.1 重写方法 重写方法是Java中的一种重要手段 指在一个类的子类里,对父类的一个方法进行重新定义! 而父类的权限级别要大于等于子类~ 【除了

    2023年04月16日
    浏览(10)
  • JavaEE & UDP简易翻译服务器 & 网络编程示例2 & CTP回显服务器,回显客户端

    JavaEE & UDP简易翻译服务器 & 网络编程示例2 & CTP回显服务器,回显客户端

    禁止白嫖 T T 点点赞呗 这个翻译器主要是在上一章的回显服务器和回显客户端上进行修改 修改了计算响应的过程, 即process方法 1.1 重写方法 重写方法是Java中的一种重要手段 指在一个类的子类里,对父类的一个方法进行重新定义! 而父类的权限级别要大于等于子类~ 【除了

    2023年04月16日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包