• 基于TCP与UDP网络编程


     一.什么是TCP与UDP

     TCP与UDP是计算机网络中五层模型的运输层协议。

    TCP 协议:是传输控制协议,它是面向连接的协议,支持可靠传输和双向通信。它在传输数据之前需要先建立连接,建立连接后才能传输数据,传输完后还需要断开连接。TCP协议之所以能保证数据的可靠传输,是通过接收确认、超时重传这些机制实现的。并且,TCP协议允许双向通信,即通信双方可以同时发送和接收数据。

    UDP协议:(User Datagram Protocol)是一-种数据报文协议,它是无连接协议,不保证可 靠传输。 因为UDP协议在通信前不需要建立连接,因此它的传输效率比TCP高,而且UDP 协议比TCP协议要简 单得多

    二.什么是Socket

            在我们进行网络编程时,都会接触到一个名叫scoket的概念,应用程序通过Scoket来建立远程连接,Socket通过内部封装好的协议把数据传输到网络。

            为什么需要Socket 进行网络通信?因为仅仅通过IP地址进行通信是不够的,同一台计算机同- -时间会运行多个网络应用程序,例如浏览器、QQ、邮件客户端等。当操作系统接收到一个数据包的时候,如果 只有IP地址,它没法判断应该发给哪个应用程序,所以,操作系统抽象出Socket 接口,每个应用程序需 要各自对应到不同的Socket,数据包才能根据 Socket正确地发到对应的应用程序。

            使用Socket进行网络编程时,本质上就是两个进程之间的网络通信。其中一个进程必须充当服务器端,它会主动监听某个指定的端口,另一个进程必须充当客户端,它必须主动连接服务器的IP地址和指定端口,如果连接成功,服务器端和客户端就成功地建立了一个TCP连接,双方后续就可以随时发送和接收,因此,当Socket 连接成功地在服务器端和客户端之间建立后:对服务器端来说,它的Socket是指定的IP地址和指定的端口号。


    三.TCP网络编程简单实现

            TCP的编程实现客户端与服务器端交互,是通过建立连接,从而利用“流”来进行数据交换的,即使用字节输入/输出流,把要发送的数据,存储到字节数组,通过“流”来实现发送与接收。

    接下来我们以客户端向服务器端上传图片的简单例子来说明TCP编程。

    1.建立服务器端

    第一步:建立socket,服务器端使用java提供的ServerSocket创建于客户端交互的对象,并且监听指定端口。

    第二步:建立与客户端的连接,创建一个Scoket,调用accept()方法,与客户端建立连接,并且获取客户端的IP地址

    第三步:创建输入流,来读取客户端上传的照片使用:getInputStream()

    第四步:创建输出流,对客户端上传的图片,写入到本地,我们这里使用BufferedInputStream来实现建立字节字节数组对传过来的数据进行批量写入。

    第六步:当我们成功接收到客户端上传的图片以后,要给客户端发送一个反馈,这时,我们需要创建一个输出流,向客户端进行反馈。

    完整的实例代码如下:

    1. try {
    2. //ServerSocket:服务器端进行通信的对象
    3. ServerSocket server = new ServerSocket(8848);
    4. //死循环:不断接收客户端的连接
    5. while(true) {
    6. //服务器进入“等待”状态
    7. //如果有客户端连接时,该方法1返回客户端的Socket
    8. Socket cilent = server.accept();
    9. InetAddress clientNetAddress = cilent.getInetAddress();
    10. System.out.println("客户端" +clientNetAddress + "正在连接.......");
    11. // 接收来自客户端上传的图片
    12. // 输入流:读取来自客户端发送的图片文件流
    13. // 输出流:写入本地图片
    14. String imgName = clientNetAddress.getHostAddress().replaceAll("\\.", "\\-") + ".jpg";
    15. try(InputStream in = cilent.getInputStream();
    16. BufferedInputStream bis = new BufferedInputStream(in);
    17. BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d:\\test\\aaa\\" + imgName))){
    18. // 每次读取来自客户端的图片文件流
    19. // 写入本地
    20. byte[] buff = new byte[1024];
    21. int len = -1;
    22. while((len = bis.read(buff)) != -1) {
    23. bos.write(buff,0,len);
    24. }
    25. System.out.println("图片读取完毕!");
    26. // 输出提示信息 => 客户端
    27. try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(cilent.getOutputStream()));){
    28. writer.write("上传完毕!");
    29. writer.newLine();
    30. }
    31. }
    32. }
    33. } catch (IOException e) {
    34. e.printStackTrace();
    35. }

    我们这里用到了一个死循环,是为了保证服务器端可以持续不断地接收来自客户端上传的图片。

    2.建立客户端

    相比服务器端,客户端就简单很多

    第一步:创建Socket,用于和服务器端进行连接的组件,传入服务器端的IP地址与端口号。

    第二步:创建一个输出流,将要上传的图片发送至服务器端。

    第三步:创建输入流,来获取将要发送的本地的图片的路径,我们这里也使用BufferedInputStream来对本地图片进行一个批量读取,将读取到的内容发送至服务器端。

    这里值得注意的是:使用cilent.shutdownOutput(),输出暂时结束(Socket没有关闭)

    第四步:我们等待服务器端接收成功后,发生给我们一个反馈,我们需要创建一个Socket的输入流,来接收服务器端对我们的反馈。

    基本实现代码如下:

    1. //Socket:客户端进行通讯的组件
    2. //本地图片获取 = > 通过输出流,发送(输出)至服务器
    3. //OutputStream:输出流,读取到本地图片文件流,发送(输出)至服务器
    4. //BufferedInputStream:输入流,读取本地文件
    5. try (
    6. Socket cilent = new Socket("192.168.254.188",8848);
    7. OutputStream out = cilent.getOutputStream();
    8. BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\数据分析\\2017年第一季度各产业生产总值占比饼图.png"))) {
    9. //每次读取到1024字节
    10. byte[] buff = new byte[1024];
    11. int len = -1;
    12. while((len = bis.read(buff)) != -1) {
    13. //将读取到的内容,通过输出流发送至服务器
    14. out.write(buff);
    15. }
    16. //输出暂时结束(Socket没有关闭)
    17. cilent.shutdownOutput();
    18. //读取来自服务器的反馈
    19. try(BufferedReader reader = new BufferedReader(new InputStreamReader(cilent.getInputStream()));){
    20. String reply = reader.readLine();
    21. System.out.println("服务器的反馈:" + reply);
    22. }
    23. } catch (IOException e) {
    24. e.printStackTrace();
    25. }

    四.UDP网络编程简单实现

    UDP和TCP相比,就简单的多,因为UDP不需要建立连接,也就没有区分哪一个是客户端哪一个是服务器端,是依靠数据包来进行实现的,数据包也是收一个发一个,不存在使用流的概念。

    UDP也是需要使用Socket来监听端口的的,不过它使用的是java提供的DatagramSocket。

    我们以一个简易的聊天室的案例,来实现简单的UDP编程:

    第一步:创建Scanner 来进行对话的输入

    第二步:创建Socket,来监听端口。

    第三步:创建两个数据包来实现对话的发送与接收。

    1.发送:

    这里使用的是DatagramPacket,传入一个字节数组,并且传入将要发送的IP地址与端口号

    使用socket.send(sendPacket),来进行发送

    1. try (DatagramSocket socket = new DatagramSocket(6666);) {
    2. //提前创建两个Packet数据包,分别用于发送和接收
    3. DatagramPacket sendPacket =
    4. new DatagramPacket(
    5. new byte[1024],1024, //数据
    6. new InetSocketAddress("192.168.254.153",7788) //目的地
    7. );
    8. while(true) {
    9. //发送
    10. System.out.print("你说:");
    11. String sendContent = input.nextLine();
    12. sendPacket.setData(sendContent.getBytes());
    13. socket.send(sendPacket1);
    14. if(sendContent.equals("滚")) {
    15. System.out.println("我不想跟你讲话");
    16. return;
    17. }
    18. socket.send(sendPacket);

    sendPacket.setData(sendContent.getBytes())

    是将输入的数据存入数据包中

    2.接收

    首先建立一个接收的数据包,传入一个自定义的字节数组,用来接收数据

    DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);

    使用socket.receive(receivePacket),方法来进行数据包的接收

    由于接收到的是一个数据包,我们如果想正常显示,就要把它变成字符串

    1. //packet.getData():获取数据包中的“数据”(字节数组)
    2. //packet.getOffset():获取数据包中的“读取位置”
    3. //packet.getLength():获取数据包中的“长度”
    4. String receiveContent = new String(receivePacket.getData(),receivePacket.getOffset(),receivePacket.getLength());

    当我们想要不停地与对方进行聊天时,就可以写一个死循环while(true){},来一直输入内容,直到输入关键字,程序才会退出。

    代码实现:

    1. //接收
    2. socket.receive(receivePacket);
    3. String receiveContent = new String(receivePacket.getData(),receivePacket.getOffset(),receivePacket.getLength());
    4. if(receiveContent.equals("滚")) {
    5. System.out.println("他不想跟你说话!");
    6. break;
    7. }
    8. system.out.println("他说:" + receiveContent);
    9. }

    运行结果:

  • 相关阅读:
    常见分布式事务解决方案
    Linux下通过bonding技术实现网络负载均衡
    M1本地部署Stable Diffusion
    prometheus返回的数据结构如何转为自定义结构
    R语言使用dplyr包的rename函数为dataframe数据中的所有列重命名
    OpenHarmony3.0如何轻松连接华为云IoT设备接入平台?
    最新最全阿里内推830道面试题合集,BATJ都有问到
    kile5上的一栏快捷键消失了,我手贱删了
    Double精度丢失问题排查及解决思路
    HTML进阶(5)- 其他元素
  • 原文地址:https://blog.csdn.net/qq_59616295/article/details/125827320