• UDP数据报套接字编程入门


    目录

    1.TCP和UDP的特点及区别

    1.1TCP的特点

     1.2UDP的特点

     1.3区别

    2.UDP Socket的api的介绍

    2.1DatagramSocket API

    2.2DatagramPacket API  

    3.回显客户端与服务器

    3.1回显服务器

    3.1.1UdpEchoServer类的创建

    3.1.2服务器的运行方法start()

    3.1.3main部分

     3.1.4.完整代码

     3.2回显客户端

    3.2.1UdpEchoClient类的创建

     3.2.2客户端的运行方法start()

    3.2.3main部分 

    3.2.4 完整代码


    1.TCP和UDP的特点及区别

    想要进行网络编程,都需要使用到系统的API。本质上都是传输层提供的。传输层涉及到的协议主要有两个。TCP和UDP,他俩的api差异很大。

    TCP和UDP都是Socket套接字针对的传输层协议划。

    Socket 套接字,是由系统提供用于网络通信的技术,是基于 TCP/IP 协议网络通信的基本操作单元。基 于Socket 套接字的网络程序开发就是网络编程

    1.1TCP的特点

    流套接字 :使用传输层 TCP 协议  
    以下为TCP的特点
    1.有连接
    2.可靠传输
    3.面向字节流
    4.有接收缓冲区,也有发送缓冲区
    5.大小不限
    对于字节流来说,可以简单的理解为,传输数据是基于 IO 流,流式数据的特征就是在 IO 流没有关闭的情 况下,是无边界的数据,可以多次发送,也可以分开多次接收。

     1.2UDP的特点

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

    以下为UDP的特点

    1.无连接
    2.不可靠传输
    3.面向数据报
    4.有接收缓冲区,无发送缓冲区
    5.大小受限:一次最多传输 64k

     1.3区别

    (1)有/无 连接

    网络中谈到的连接,本质上是通信双方各自保存双方信息。

    有连接是通信双方都要同意。如:微信发电话。

    无连接是收方无论是否同意,都会收到信息。如:微信发消息。

    (2)可/不可 靠传输

    由于网络上存在的异常情况非常的多,无法保证网络数据100%通信成功。

    可靠传输 是指发送方知道自己发送的信息是否成功送达。反之不知道则是不可靠传输

    (3) 面向数据报/字节流

    指的是网络中传输的基本单位是数据报/字节流。


    2.UDP Socket的api的介绍

    2.1DatagramSocket API

    DatagramSocket UDP Socket,用于发送和接收UDP数据报。

    socket 文件抽象了“网卡”这样的硬件设备。

    (1)DatagramSocket 构造方法:

     (2)DatagramSocket 方法:

    2.2DatagramPacket API  

    DatagramPacketUDP Socket发送和接收的数据报。 

    (1)DatagramPacket 构造方法:

     (2)DatagramPacket 方法:

    构造UDP发送的数据报时,需要传入 SocketAddress ,该对象可以使用 InetSocketAddress 来创建。

    InetSocketAddress API
    InetSocketAddress SocketAddress 的子类 )构造方法:


    3.回显客户端与服务器

    什么叫回显客户端与与服务器呢?

    其实就是:客户端向服务端发送请求,一般来说我们的服务端会对我们发送的请求进行处理,我们这里为了简单,就省略里面的处理过程,只实现将请求重新发回客户端,不做任何处理。

    3.1回显服务器

    3.1.1UdpEchoServer类的创建

    1.需要创建一个DatagramSocket对象,因为需要操作网卡。

    代码:

    1. public class UdpEchoServer {
    2. private DatagramSocket socket=null;
    3. public UdpEchoServer(int port) throws SocketException {
    4. socket=new DatagramSocket(port);
    5. }
    6. }

    代码说明:

    (1)socket=new DatagramSocket(port);

    在运行一个服务器的时候,通常会手动指定一个端口号。

    补:一个主机上的端口号,只能被一个进程绑定,但一个进程可以绑定多个端口号。 

    (2)throws SocketException

    通常表示socket创建失败。

    比如:端口号已经被别的进程占用了。

    3.1.2服务器的运行方法start()

    工作内容:

    1. 读取请求并解析

    2. 根据请求计算响应 (对于 回显服务器来说, 这一步啥都不用做)

    3. 把响应返回到客户端.

    4.打印日志

     代码:

    1. import java.io.IOException;
    2. import java.net.*;
    3. public class UdpEchoServer {
    4. private DatagramSocket socket = null;
    5. public UdpEchoServer(int port) throws SocketException {
    6. socket = new DatagramSocket(port);
    7. }
    8. public void start() throws IOException {
    9. System.out.println("服务器启动");
    10. while (true) {
    11. DatagramPacket requestpacket = new DatagramPacket(new byte[4096], 4096);
    12. socket.receive(requestpacket);
    13. String request = new String(requestpacket.getData(), 0, requestpacket.getLength());
    14. String response = process(request);
    15. DatagramPacket responsepacket = new DatagramPacket(response.getBytes(), response.getBytes().length, requestpacket.getSocketAddress());
    16. socket.send(responsepacket);
    17. // 打印日志
    18. System.out.printf("[%s:%d] req: %s, resp: %s\n", requestpacket.getAddress().toString(),
    19. requestpacket.getPort(), request, response);
    20. }
    21. }
    22. private String process(String request) {
    23. return request;
    24. }
    25. }

    代码说明:

    1.  while (true) {~~~}

    对于服务器来说,需要不停的收到请求,返回响应,收到请求,返回响应

    2.    DatagramPacket requestpacket = new DatagramPacket(new byte[4096], 4096);

    (1)byte[4096]->4096 表示的是载荷长度。

    这个数组存的是消息正文(应用层数据包)也就是UDP数据包载荷部分。

    (2) socket.receive(requestpacket);

    如果执行到socket.receive(requestpacket)的时候,还没有客户端发来请求,则会先堵塞等待。

    (3 )requestpacket.getSocketAddress()

    由于requestpacket是从客户端来的数据报,故得到的InetAddress对象就会包含了客户端的IP和端口号。

    3.1.3main部分

    代码:

    1. public static void main(String[] args) throws IOException {
    2. UdpEchoServer server = new UdpEchoServer(9090);
    3. server.start();
    4. }

    代码说明:

    UdpEchoServer server = new UdpEchoServer(9090);

    9090->这个端口号可以指定任何你想要指定的端口号。

     3.1.4.完整代码

    代码:

    1. package network;
    2. import java.io.IOException;
    3. import java.net.DatagramPacket;
    4. import java.net.DatagramSocket;
    5. import java.net.SocketException;
    6. import java.nio.charset.StandardCharsets;
    7. public class UdpEchoServer {
    8. private DatagramSocket socket = null;
    9. public UdpEchoServer(int port) throws SocketException {
    10. socket = new DatagramSocket(port);
    11. }
    12. // 服务器的启动逻辑.
    13. public void start() throws IOException {
    14. System.out.println("服务器启动!");
    15. while (true) {
    16. // 每次循环, 就是处理一个请求-响应过程.
    17. // 1. 读取请求并解析
    18. DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
    19. socket.receive(requestPacket);
    20. // 读到的字节数组, 转成 String 方便后续的逻辑处理.
    21. String request = new String(requestPacket.getData(), 0, requestPacket.getLength());
    22. // 2. 根据请求计算响应 (对于 回显服务器来说, 这一步啥都不用做)
    23. String response = process(request);
    24. // 3. 把响应返回到客户端.
    25. // 构造一个 DatagramPacket 作为响应对象
    26. DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), response.getBytes().length,
    27. requestPacket.getSocketAddress());
    28. socket.send(responsePacket);
    29. // 打印日志
    30. System.out.printf("[%s:%d] req: %s, resp: %s\n", requestPacket.getAddress().toString(),
    31. requestPacket.getPort(), request, response);
    32. }
    33. }
    34. public String process(String request) {
    35. return request;
    36. }
    37. public static void main(String[] args) throws IOException {
    38. UdpEchoServer server = new UdpEchoServer(9090);
    39. server.start();
    40. }
    41. }

     3.2回显客户端

    3.2.1UdpEchoClient类的创建

    代码:

    1. import java.io.IOException;
    2. import java.net.*;
    3. import java.util.Scanner;
    4. public class UdpEchoClient {
    5. private DatagramSocket socket = null;
    6. private String serverIp;
    7. private int serverPort;
    8. public UdpEchoClient(String serverIp,int serverPort) throws SocketException {
    9. this.socket = new DatagramSocket();
    10. this.serverIp = serverIp;
    11. this.serverPort = serverPort;
    12. }
    13. }

     代码说明:

    (1)this.socket = new DatagramSocket();

    客户端这边一般不会手动指定端口好,会让系统自动分配一个端口号。

    (2)private String serverIp;
             private int serverPort; 

      客户端需要主动给服务器发送请求,发送请求的前提是知道服务器在哪。

     3.2.2客户端的运行方法start()

    工作内容:

    1. 从控制台读取要发送的请求数据.

    2. 构造请求并发送

    3. 读取服务器的响应.

    4. 把响应显示到控制台上

    代码:

    1. public void start() throws IOException {
    2. System.out.println("客户端启动");
    3. Scanner scanner = new Scanner(System.in);
    4. while (true){
    5. System.out.print("->");
    6. if(!scanner.hasNext()){
    7. break;
    8. }
    9. String request=scanner.next();
    10. DatagramPacket requestpacket=new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(serverIp),serverPort);
    11. socket.send(requestpacket);
    12. DatagramPacket responsepacket=new DatagramPacket(new byte[4096],4096);
    13. socket.receive(responsepacket);
    14. String response=new String(responsepacket.getData(),0,responsepacket.getLength());
    15. System.out.println(response);
    16. }
    17. }

      代码说明:

    InetAddress.getByName(serverIp)

    把数据的单位从字符->字节。

    3.2.3main部分 

    代码:

    1. public static void main(String[] args) throws IOException {
    2. UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);
    3. client.start();
    4. }
    3.2.4 完整代码

    代码:

    1. import java.io.IOException;
    2. import java.net.*;
    3. import java.util.Scanner;
    4. public class UdpEchoClient {
    5. private DatagramSocket socket = null;
    6. private String serverIp;
    7. private int serverPort;
    8. // 此处 ip 使用的字符串, 点分十进制风格. "192.168.2.100"
    9. public UdpEchoClient(String serverIp, int serverPort) throws SocketException {
    10. this.serverIp = serverIp;
    11. this.serverPort = serverPort;
    12. socket = new DatagramSocket();
    13. }
    14. public void start() throws IOException {
    15. System.out.println("客户端启动");
    16. Scanner scanner = new Scanner(System.in);
    17. while (true) {
    18. // 要做四个事情
    19. System.out.print("-> "); // 表示提示用户接下来要输入内容.
    20. // 1. 从控制台读取要发送的请求数据.
    21. if (!scanner.hasNext()) {
    22. break;
    23. }
    24. String request = scanner.next();
    25. // 2. 构造请求并发送.
    26. DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,
    27. InetAddress.getByName(serverIp), serverPort);
    28. socket.send(requestPacket);
    29. // 3. 读取服务器的响应.
    30. DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);
    31. socket.receive(responsePacket);
    32. // 4. 把响应显示到控制台上.
    33. String response = new String(responsePacket.getData(), 0, responsePacket.getLength());
    34. System.out.println(response);
    35. }
    36. }
    37. public static void main(String[] args) throws IOException {
    38. UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);
    39. // UdpEchoClient client = new UdpEchoClient("139.155.74.81", 9090);
    40. client.start();
    41. }
    42. }

    运行结果:

    小结 :


    以上为我个人的小分享,如有问题,欢迎讨论!!! 

    都看到这了,不如关注一下,给个免费的赞 

  • 相关阅读:
    Web 端项目系统访问页面很慢,后台数据返回很快,网络也没问题,是什么导致的呢?
    上传npm包到私有nexus仓库中《解决服务端安装npm依赖失败的问题》
    mac下安装redis
    LAS、CTC、RNN-T、NT、MoChA
    c语言打印菱形图案
    [golang]channel源码
    MyBatis 操作数据库(构造动态 SQL)
    ChatGPT手机电脑浏览器中使用免费的ChatGPT
    List集合
    管理团队相关的梳理
  • 原文地址:https://blog.csdn.net/WHabc2002/article/details/136356444