UDP,TCP特点对比,DatagramPacket,SocketAddress的使用 ,UDP的API,如何编写一个简单的回显服务器及客户端,详细解释(本文内容较难,建议多次阅读,自己敲一敲)

简介: UDP,TCP特点对比,DatagramPacket,SocketAddress的使用 ,UDP的API,如何编写一个简单的回显服务器及客户端,详细解释(本文内容较难,建议多次阅读,自己敲一敲)

一、💛

传输层提供协议主要有两个:(两套有不同的API)

1.UDP:无连接,不可靠传输,面向数据报,全双工

2.TCP:有连接,可靠传输,面向字节流,全双工

有/无连接,如同JDBC(看我之前写的里面),先创建一个DataSource,再通过DataSource创建Connection->(TCP编程,也存在这种类似建立连接的过程。

客户端和服务器之间,使用“内存”保存对端信息~~,双方都保存这个信息,此时连接就存在,客户端可以连多个服务器,服务器也可以连接多个客户端。

链接(和连接是不一样的)——其实就是快捷方式,也叫符号链接

TCP可靠传输(效果也会因为可靠而降低):A尽可能的传递给B,并且假如传输失败的时候,A能感知到,成功的时候哦,自己也能知道,自己传递成功了。

UDP不可靠传输(效率偏高一点)

注意⚠️:可靠和安全是两回事,谈到的网络安全,你是否容易被黑客捕获,以及如果捕获后,会不会泄露一些重要信息。

面向字节流,面向数据报:这两种特性很影响代码编写。

TCP和文件操作类似(都是流式,这里传输单位是字节,成为字节流)通过TCP读写100字节数据,可一次读写100字节,当然也可以拆分,一次读10,读10次等等。

UDP的数据报,读写的基本单位,是一个UDP数据报(包含一系列数据属性)

全双工:一个通道,可以双向通信

半双工:一个通道,可单向通信

二、💙

UDP的socket. API

1.DatagramSocket:是一个Socket对象,操作系统,使用文件这样的概念,来管理一些软硬件资源,网卡,操作系统,也是用文件这样的方式管理网卡,表示网卡这类文件成为Socket文件。JAVA中的socket对象,就对应系统里的socket文件(最终管理到网卡),要进行网络通信,要先有socket对象

DatagramSocket():在客户端这边使用,客户端使用哪个端口,系统是自动分配的

DatagramSocket(int port):在服务器这边使用,服务器使用哪个端口是我们手动指定的。

2.DatagramPacket:

表示一个UDP数据报,代表系统中设定的UDP数据报的二进制结构

这就如同:

大学六厅,9号窗口西安里凉皮<->相当于服务器端口(固定好找),大学六厅就相当于IP地址,同学们坐的位置就相当于客户端端口号,你下次来是找空位,而不是上次的座位,但是9号窗口:客户端的端口号是要求固定的

一个客户端主机,上面运行的程序很多,不知道,你手动指定的端口是不是被别的程序占用 ,让系统自动分配一个端口是更明智的选择,服务器是完全在程序员手里控制的,程序员可以把服务器上多个程序安排好,让他们使用不同的端口。

DatagramSocket提供了三个方法。  

void receive(DatagramPacket p)

        send(DatagramPacket p):发送

        close()关闭

DatagramPacket :表示一个UDP数据报,代表系统中设定的UDP数据报的二进制结构

DatagramPacket(byte[]buf,int length)->接受数组

DatagramPacket(byte[]buf,int offset,int length,SocketAddress address(目的端口和目的IP) )

DatagramPacket作为UDP数组报,必然要承载一些数据,通过手动指定的byte[]作为存储数据的空间。

三个方法(知道就好):

InetAddress getAdress():从接收的数据报中,获取发送端主机IP地址,或从发送的数据报中,获取接收端主机IP地址

int getPort():从接收数据报中,获取发送端主机的端口号,或从发送的数据报中,获取接受端的主机端口号。

byte []getData:获取数据报中的数据

开始写UDP客户端服务器——新的流程

最简单的UDP服务器,回显服务器(客户端发啥,服务器就返回什么东西),编写网络程序,经常会见到SocketException这个异常

最典型的情况,端口号被占用,端口号用来区分主机上的应用程序,一个应用程序可以占据主机上多个端口,一个端口只能被一个进程占用(这话其实也不太严谨,但此处不做讨论)端口已经被别的进程占用了,此时你再创建这个socket对象,占用该端口,就会报错。

一个服务器要给很多用户的客户端提供服务,服务器也不知道客户端什么时候来,服务器只能时刻准备着,随时客户端来了,随时提供服务。

写服务器三个步骤

1.读取请求,并解析

2.根据请求,计算出响应

回显服务器,并不关注这个,但是正经的服务器,主要代码都是在完成这个模块,(处理一个请求,可能会经历几万行的代码,几十万行代码构建出来的逻辑)

3.把响应写回客户端

介绍方法

1.socket.receive():这方法,参数DatagramPacket是一个“输出型参数”,传入receive是一个空的对象,receive内部就会把这个内容填充上,当receive执行结束,于是就得到了一个装满内容的DatagramPacket.(幻想,你把餐盘(DatagramPacket)给食堂大姨,食堂大姨给你添饭(receive),小伙盘子给你,你拿回去

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

这个4096,你随便写,无所谓,但最好别太大,也别太小,这个对象用来保存数据的内存空间,是需要手动指定的,不像我们之前的集合类,能自动申请,释放,扩容内存

3.utf8中,一个汉字,三个字节,我们的String s ——s.length——s.getBytes().length,一个是按照字节存储的,一个是按照字符存储,英文还好,但是假如说是中文,中文的话两个字,是两个字符还是6个字节就有区别了。

4.

DatagramPacket responsePacket=new Datagrampacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());

response.getBytes():接收的字符串数组

response.getBytes().length:字节长度

requestPacket.getSocketAddress():发给谁,目的端口,IP,要构造一个DatagramPacket对象,把响应发给客户端

三、💜

回显代码的服务器具体实现

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UdpEchServer {
    private DatagramSocket socket = null;
    //服务器需要绑定的窗口
    public UdpEchServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }
    public void start() throws IOException {
        System.out.println("服务器启动");
        while (true) {
//申请一个4096的字符串数组取装你的语句回显。
            DatagramPacket requestPacker = new DatagramPacket(new byte[4096], 4096);
//接收这个字符串(在客户端来临之前,他会一直停止在这个地方等待)
            socket.receive(requestPacker);
//这句话应该是相当于把你哪个语句内容,放到一个字符串里面。
            String request = new String(requestPacker.getData(), 0, requestPacker.getLength());
            //2.根据请求,计算出响应(由于这个是回显,所以直接返回你的输入值就行,也就是上面的字符串)
            String response = process(request);
            //3.把响应写回客户端,此时需要告知网卡,要发的内容是什么,发给谁。
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), response.getBytes().length, requestPacker.getSocketAddress());
            //4.把这个发的内容,重新返回给客户端
            socket.send(requestPacker);
//返回之后给他打印一样,C语言的printf
            System.out.printf("[%s:%d] rep:%s,resp:%s\n", requestPacker.getAddress().toString(), requestPacker.getPort(), request, response);
        }
    }
    public String process(String request) {
        return request;
    }
    public static void main(String[] args) throws IOException {
        UdpEchServer server = new UdpEchServer(9090);
        server.start();
    }
}

四、❤️

回显服务器客户端的编写

import java.io.IOException;
import java.net.*;
import java.util.Scanner;
public class UdpEchoClient {
//第一个是用来装客户端发的语句并且传输给服务器的。
    private DatagramSocket socket=null;
//下面两个是本机的IP和连接服务器的端口
    private  String serverIP;
    private  int serverPort;
    public UdpEchoClient(String ip,int port) throws SocketException {
        serverIP = ip;
        serverPort = port;
        socket=new DatagramSocket();
    }
    //让这个客户端反复从控制台读取用户输入的内容,把这个过程构造成UDP的请求,发给服务器,再读取服务器返回的UDP响应
    //最终显示在客户端屏幕上
    public  void start() throws IOException {
        Scanner scanner=new Scanner(System.in);
        System.out.println("客户端启动");
        while(true){
            //1.从控制台读取用户制定的内容
            System.out.println("->");
//输入你要输入的语句。
            String request= scanner.next();
            //2.构造请求对象,并且把你的语句打包,并且发给服务器
//request.getBytes():字符串的字节数组
//request.getBytes().length:字节数组长度
//InetAddress.getByName(serverIP):本机的IP,此时需要的是InetAddress对象,使用inetAddress的静态方法,getByName来进行构造(工厂模式,工厂方法)
//serverPort:服务器的端口号
            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);
            String response=new String(responsePacket.getData(),0,responsePacket.getLength());
            //4.显示到屏幕上
            System.out.println(response);
        }
    }
    public static void main(String[] args) throws IOException {
//127.0.0.1是用来访问本机地址的
        UdpEchoClient client=new UdpEchoClient("127.0.0.1",9090);
        client.start();
    }
}

五、 💚

我们如何开启多个客户端呢?

1.点击我点击的地方

2.点🐔这个more的这个东西

3.勾选第一个选项(第二个原来就有),然后退出点击OK保存就可以。

最终的呈现结果

总结:这个勾八内容挺复杂,自己去写一写,感受一下。


相关文章
|
网络协议 Java API
【JavaEE】——Udp翻译器的实现(回显服务器)
网络编程,DatagramSocket 和 DatagramPacket类,回显服务器,服务器实现,客户端实现,
|
存储 网络协议 Java
【网络】UDP回显服务器和客户端的构造,以及连接流程
【网络】UDP回显服务器和客户端的构造,以及连接流程
438 3
|
存储 网络协议 Java
【网络】UDP和TCP之间的差别和回显服务器
【网络】UDP和TCP之间的差别和回显服务器
291 1
|
负载均衡 API 数据安全/隐私保护
Zookeeper的客户端-原生的API
Zookeeper的客户端-原生的API
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
1433 1
|
9月前
|
弹性计算 运维 安全
阿里云轻量应用服务器与云服务器ECS啥区别?新手帮助教程
阿里云轻量应用服务器适合个人开发者搭建博客、测试环境等低流量场景,操作简单、成本低;ECS适用于企业级高负载业务,功能强大、灵活可扩展。二者在性能、网络、镜像及运维管理上差异显著,用户应根据实际需求选择。
800 10
|
9月前
|
弹性计算 ice
阿里云4核8g服务器多少钱一年?1个月和1小时价格,省钱购买方法分享
阿里云4核8G服务器价格因实例类型而异,经济型e实例约159元/月,计算型c9i约371元/月,按小时计费最低0.45元。实际购买享折扣,1年最高可省至1578元,附主流ECS实例及CPU型号参考。
854 8
|
9月前
|
运维 安全 Ubuntu
阿里云渠道商:服务器操作系统怎么选?
阿里云提供丰富操作系统镜像,涵盖Windows与主流Linux发行版。选型需综合技术兼容性、运维成本、安全稳定等因素。推荐Alibaba Cloud Linux、Ubuntu等用于Web与容器场景,Windows Server支撑.NET应用。建议优先选用LTS版本并进行测试验证,通过标准化镜像管理提升部署效率与一致性。
|
9月前
|
存储 监控 安全
阿里云渠道商:云服务器价格有什么变动?
阿里云带宽与存储费用呈基础资源降价、增值服务差异化趋势。企业应结合业务特点,通过阶梯计价、智能分层、弹性带宽等策略优化成本,借助云监控与预算预警机制,实现高效、可控的云资源管理。
|
9月前
|
弹性计算 运维 安全
区别及选择指南:阿里云轻量应用服务器与ECS云服务器有什么区别?
阿里云轻量应用服务器适合个人开发者、学生搭建博客、测试环境,易用且性价比高;ECS功能更强大,适合企业级应用如大数据、高流量网站。根据需求选择:轻量入门首选,ECS专业之选。
635 2

热门文章

最新文章