Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显

这篇具有很好参考价值的文章主要介绍了Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Socket 套接字

我们软件工作者,着重编写的是应用层的代码,但是发送这个数据,我们就需要将应用层传输到传输层,也就意味着我们需要调用应用层的API,统称为 Socket API。

套接字的分类:

  1. 流套接字:使用传输层TCP协议
    特点:
    • 有连接:使用 TCP 通信的双方,需要时刻保存对方的相关消息
    • 可靠传输:尽可能的将数据传输过去,如果没有传输过去,自己也知道没有传输,然后通过设定可以重新传输
    • 面向字节流:以字节为传输的基本单位,读写方式更为灵活
    • 全双工:一条路径,双向通信
  2. 数据报套接字:使用传输层UDP协议
    特点:
    • 有连接:使用 UDP 通信的双方,不需要时刻保存对方的相关消息
    • 不可靠传输:只关注是否传输了数据,至于是否传输成功,并不专注
    • 面向数据报:以一个UDP数据报为基本单位
    • 全双工:一条路径,双向通信
  3. 原始套接字:原始套接字用于自定义传输层协议,用于读写内核没有处理的IP协议数据。
    所有特点自己定义

什么是全双工和半双工?

全双工:一条路径,双向通信
半双工:一条路径,单向通信

网络传输数据的基本单位:报(Datagram)、包(Packet)、段(Segment)、帧(Frame)
Socket 对象,相当于系统中Socket文件,这个文件并非对应到硬盘上的某个数据存储区域,而是对应到网卡这个硬件设备

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

这个图不是我画,摘抄了网上现有的)
Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显,java,网络,java,tcp/ip

数据报套接字UDP

java中使用UDP协议通信,主要基于 DatagramSocket 类来创建数据报套接字,并使用DatagramPacket 作为发送或接收的UDP数据报 。DatagramSocket 是UDP Socket,用于发送和接收UDP数据报。

DatagramSocket API:

  1. DatagramSocket 构造方法

Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显,java,网络,java,tcp/ip

  1. DatagramSocket 方法:
    Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显,java,网络,java,tcp/ip

DatagramPacket API:(DatagramPacket是UDP Socket发送和接收的数据报)

  1. DatagramPacket 构造方法:
    Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显,java,网络,java,tcp/ip

  2. DatagramPacket 方法:
    Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显,java,网络,java,tcp/ip
    构造UDP发送的数据报时,需要传入 SocketAddress ,该对象可以使用 InetSocketAddress 来创

InetSocketAddress API:

  1. InetSocketAddress ( SocketAddress 的子类 )构造方法:
    Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显,java,网络,java,tcp/ip

UDP服务器:

注意:

  • 服务器的端口必须不变,客户端这边则不需要手动指定,系统自动分配
  • socket是文件,也需要关闭
public class UdpServer { 
    //服务器socket要绑定固定的端口 
    private static final int PORT = 8888; 
    public static void main(String[] args) throws IOException { 
        // 1.创建服务端DatagramSocket,指定端口,可以发送及接收UDP数据报 
        DatagramSocket socket = new DatagramSocket(PORT); 
        //不停的接收客户端udp数据报 
        while (true){ 
            // 2.创建数据报,用于接收客户端发送的数据 
            byte[] bytes = new byte[1024];//1m=1024kb, 1kb=1024byte, UDP最多64k(包含UDP首部8byte) 
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length); 
            System.out.println("---------------------------------------------------"); 
            System.out.println("等待接收UDP数据报..."); 
            // 3.等待接收客户端发送的UDP数据报,该方法在接收到数据报之前会一直阻塞,接收到数据报以后,DatagramPacket对象,包含数据(bytes)和客户端ip、端口号 
            socket.receive(packet); 
            System.out.printf("客户端IP:%s%n",  
			packet.getAddress().getHostAddress()); 
            System.out.printf("客户端端口号:%s%n", packet.getPort()); 
            System.out.printf("客户端发送的原生数据为:%s%n",  
			Arrays.toString(packet.getData())); 
            System.out.printf("客户端发送的文本数据为:%s%n", new 
			String(packet.getData())); 
       } 
   } 
}

一旦服务器一起动,调用start方法,就会立即执行到,receive这里,但是如果此时还有没有客户端发来的数据,receive就会阻塞等待,一直持续到有数据发过来。
细节:网卡这里收到数据,就会进行分用,解析UDP这一层 看到端口号,然后将数据放入接收缓冲区,然后将数据到了参数中的DatagramSocket 对象中

UDP客户端:

public class UdpClient { 
    // 服务端socket地址,包含域名或IP,及端口号 
    private static final SocketAddress ADDRESS = new 
	InetSocketAddress("localhost", 8888); 
    public static void main(String[] args) throws IOException { 
        // 4.创建客户端DatagramSocket,开启随机端口就行,可以发送及接收UDP数据报 
        DatagramSocket socket = new DatagramSocket(); 
        // 5-1.准备要发送的数据 
        byte[] bytes = "hello world!".getBytes(); 
        // 5-2.组装要发送的UDP数据报,包含数据,及发送的服务端信息(服务器IP+端口号) 
        DatagramPacket packet = new DatagramPacket(bytes, bytes.length, ADDRESS); 
        // 6.发送UDP数据报 
        socket.send(packet); 
   } 
}

Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显,java,网络,java,tcp/ip

TCP流套接字编程

ServerSocket API:

ServerSocket 是创建TCP服务端Socket的API。

  1. ServerSocket 构造方法:
    Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显,java,网络,java,tcp/ip
  2. ServerSocket 方法:
    Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显,java,网络,java,tcp/ip
    accept:意思就是接受,本质上是三次握手后面的文章会说。

Socket API:

Socket 是客户端 Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。
不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。

  1. Socket 构造方法:
    Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显,java,网络,java,tcp/ip
  • host 表示服务器的 IP 地址
  • port 表示服务器的端口
  1. Socket 方法:
    Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显,java,网络,java,tcp/ip
  • 从InputStream这里读数据,就相当于从网卡接收
  • 往OutputStream这里写数据,就相当于从网卡发送

TCP的长短连接

TCP发送数据时,需要先建立连接,而什么时候关闭连接就决定是短连接还是长连接。
短连接:每次接收数据并返回响应后,都关闭连接。也就是说,短连接只能一次收发。

  • 连接客户端和服务器
  • 对于客户端来说。要发送一个请求,然后接收一个响应
  • 对于服务器来说。会收到一个请求,然后返回一个响应
  • 然后关闭连接

长连接:不关闭连接,一直保持连接状态,双方不停的收发数据,即是长连接。也就是说,长连接可以
多次收发数据

  • 连接客户端和服务器
  • 可以客户端一直发送请求,并获取服务器的响应
  • 可以服务器一直发送请求,并获取客户端的响应
  • 没有一方主动停止,不关闭

长连接和短连接的区别:

  • 建立连接、关闭连接的耗时:短连接每次请求、响应都需要建立连接,关闭连接;而长连接只需要第一次建立连接,之后的请求、响应都可以直接传输。相对来说建立连接,关闭连接也是要耗时的,长连接效率更高。
  • 主动发送请求不同:短连接一般是客户端主动向服务端发送请求;而长连接可以是客户端主动发送请求,也可以是服务端主动发。
  • 两者的使用场景有不同:短连接适用于客户端请求频率不高的场景,如浏览网页等。长连接适用于客户端与服务端通信频繁的场景,如聊天室,实时游戏等。

实现一个简单回显服务器

public class TcpEchoServer {
    //serverSocket 就是外场拉客的小哥(类似集合),只有一个

    //clientSocket 内场服务的人(),会给每个客服分配一个
    private ServerSocket serverSocket=null;
    //1

    public TcpEchoServer(int port) throws IOException {
        serverSocket=new ServerSocket(port);
    }
    public void start() throws IOException {
        ExecutorService executorService= Executors.newCachedThreadPool();
        System.out.println("服务器启动");
        while (true){
            Socket clientSocket=serverSocket.accept();
            //如果直接调用,该方法会影响这个循环的二次执行.导致accept不及时了
            //创建新的线程,用新的线程来调用processConnetion
            //每次来一个新的客户端都搞一个新的线程即可
/*            Thread t=new Thread(()->{
                try {
                    processConnection(clientSocket);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
            t.start();*/
            //创建一个线程池,从池子中拿取线程
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        processConnection(clientSocket);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
        }
    }
    //通过这个方法处理一个链接
    //读取请求
    //根据请求计算响应
    //把响应返回给客户端
    private void processConnection(Socket clientSocket) throws IOException {
        System.out.printf("[%s:%d] 客户端上线!\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());
        try(InputStream inputStream=clientSocket.getInputStream();
            OutputStream outputStream=clientSocket.getOutputStream()) {
            //没有这两个也可以,但是代价就是得一个字节一个字节的处理,找到那个是结束符
            //将字节流包装成了字符流
            Scanner scanner=new Scanner(inputStream);
            PrintWriter printWriter=new PrintWriter(outputStream);
            while (true){
                //3
                //读取请求
                if (!scanner.hasNext()){
                    //读取的流到了结尾了
                    System.out.printf("[%s:%d] 客户端下线",clientSocket.getInetAddress().toString(),clientSocket.getPort());
                    break;
                }
                //直接使用scanner读取一段字符串
                String request=scanner.next();//往后读,一直读到空白符,空格,换行,翻页符....都算空白符

                //5
                //根据请求计算响应
                String response=process(request);
                //把响应返回给客户端
                printWriter.println(response);
                //刷新缓冲区
                printWriter.flush();
                System.out.printf("[%s:%d] req:%s; resp:%s\n",clientSocket.getInetAddress().toString()
                ,clientSocket.getPort(),request,response);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            clientSocket.close();
        }
    }
    private String process(String request) {
        return request;
    }

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

}

Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显,java,网络,java,tcp/ip
补充一点:

硬件的读写速度:

  • 内存 > 硬盘 > 网卡

读写硬盘和网卡口可以视为 IO 操作。

  • printWriter.println(response);----》写网卡

因为网卡读写速度慢,如果平凡的写入,读出对于效率太慢了。为了提高IO操作的效率,此时就需要引入一个内存构成的缓冲区。等缓冲区达到一定数量,就统一写入网卡中。

缓存(cache)!=缓冲区(buffer)文章来源地址https://www.toymoban.com/news/detail-702044.html

  • 缓存:只能读
  • 缓冲区:可以读也可以写。

到了这里,关于Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【网络编程】网络编程 和 Socket 套接字认识

    ✨个人主页:bit me👇 ✨当前专栏:Java EE初阶👇 用户在浏览器中,打开在线视频网站,如优酷看视频,实质是通过网络,获取到网络上的一个视频资源。 与本地打开视频文件类似,只是视频文件这个资源的来源是网络。 相比本地资源来说,网络提供了更为丰富的网络资源:

    2023年04月15日
    浏览(35)
  • 网络编程—Socket套接字详解

    目录 一、网络编程 1.1、为什么需要网络编程? 1.2、什么是网络编程 1.3、发送端和接收端 ​编辑1.4、请求和响应 ​编辑1.5、客户端和服务端  二、Socket套接字  2.1、概念 2.2、分类  2.2.1、流套接字  2.2.2、数据报套接字  2.2.3、原始套接字  2.3、Socket编程注意事项  1.1、为什

    2024年02月16日
    浏览(31)
  • 「网络编程」第二讲:网络编程socket套接字(一)

    「前言」文章是关于网络编程的socket套接字方面的,下面开始讲解! 「归属专栏」网络编程 「主页链接」个人主页 「笔者」枫叶先生(fy) 「枫叶先生有点文青病」「每篇一句」 春风得意马蹄疾,一日看尽长安花。 ——孟郊《登科后》 目录 一、预备知识 1.1 源IP和目的IP 1.

    2024年02月09日
    浏览(39)
  • [JAVAee]网络编程-套接字Socket

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

    2024年02月13日
    浏览(28)
  • 【Python】Python 网络编程 ( Socket 套接字简介 | Socket 套接字使用步骤 | Socket 套接字服务端与客户端开发 )

    Socket 套接字 是一种 进程之间的 通信机制 , 通过套接字可以在 不同的进程之间 进行数据交换 ; 在 网络编程 中 , Socket 套接字 主要用于 客户端 与 服务器 之间的 通信 , 大部分 网络相关的应用程序 , 都使用到了 Socket 套接字技术 ; 套接字有两种类型 : 流套接字 : 提供了一个可

    2024年02月15日
    浏览(41)
  • 网络编程『socket套接字 ‖ 简易UDP网络程序』

    🔭个人主页: 北 海 🛜所属专栏: Linux学习之旅、神奇的网络世界 💻操作环境: CentOS 7.6 阿里云远程服务器 在当今数字化时代,网络通信作为连接世界的桥梁,成为计算机科学领域中至关重要的一部分。理解网络编程是每一位程序员必备的技能之一,而掌握套接字编程则

    2024年02月04日
    浏览(32)
  • 【网络通信】socket编程——TCP套接字

    TCP依旧使用代码来熟悉对应的套接字,很多接口都是在udp中使用过的 所以就不会单独把他们拿出来作为标题了,只会把第一次出现的接口作为标题 通过TCP的套接字 ,来把数据交付给对方的应用层,完成双方进程的通信 在 tcpServer.hpp 中,创建一个命名空间 yzq 用于封装 在命名

    2024年02月13日
    浏览(29)
  • Linux网络编程- 原始套接字(Raw Socket)

    原始套接字(Raw Socket)提供了一种机制,允许应用程序直接访问底层传输协议,绕过操作系统提供的传输层接口。这种套接字通常用于实现新的协议或对现有协议进行低级别的操作。 以下是对原始套接字的详细介绍: 定义与用途 : 原始套接字是直接基于网络层(如IP)的。

    2024年02月07日
    浏览(31)
  • 【JavaEE初阶】 网络编程基础与Socket套接字

    用户在浏览器中,打开在线视频网站,如腾讯看视频,实质是通过网络,获取到网络上的一个视频资源。 与本地打开视频文件类似,只是视频文件这个资源的来源是 网络 。 相比本地资源来说,网络提供了更为丰富的网络资源: 所谓的网络资源,其实就是在网络中可以获取

    2024年02月05日
    浏览(38)
  • 网络编程之 Socket 套接字(使用数据报套接字和流套接字分别实现一个小程序(附源码))

    网络编程是指网络上的主机,通过不同的进程,以编程的方式实现 网络通信(或称为网络数据传输) 只要满足不同的进程就可以进行通信,所以即便是在同一个主机,只要不同的进程,基于网络传输数据,也属于网络编程 在一次网络传输中: 发送端: 数据的 发送方进程

    2024年02月03日
    浏览(37)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包