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

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


JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp
JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp
JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp


JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp

JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp
JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp


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

package network;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
//UDP的回显服务器   客户端发出的请求是啥,服务器返回的响应就是啥
public class UdpEchoServer {
    private DatagramSocket socket=null;

    //  指定服务器的port
    public UdpEchoServer(int port) throws SocketException {
        socket=new DatagramSocket(port);
    }

    //指定一个方法启动服务器
    public void start() throws IOException {
        System.out.println("服务器开始启动");
        while(true){
            // 反复的, 长期的执行针对客户端请求处理的逻辑.
            // 一个服务器, 运行过程中, 要做的事情, 主要是三个核心环节.
            //服务器这里需要接收请求
            //1.读取请求,并解析
            DatagramPacket requestPacket=new DatagramPacket(new byte[4096],4096);
            socket.receive(requestPacket);
            //解析
            String request=new String(requestPacket.getData(),0, requestPacket.getLength());
            //2.根据解析出的请求,做出响应(这里是一个回显,)
            String response=process(request);
            //3. 把响应写回客户端  此时需要告诉网卡,要发的内容是啥,发给谁
            //构造一个发送数据包
            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);
        }
    }
    //这里是一个回显,只需要返回这个字符串
    public 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 {
    //由于客户端的port是自动分配的,所以这里不会像服务器那样配置port
    //但是,客户端需要向服务器发送请求,所以,这里我们需要知道服务器的ip和port
    private DatagramSocket socket=null;
    private String serverIp;
    private int serverPort;

    //外部指定服务器的ip和port
    public UdpEchoClient(String ip,int port) throws SocketException {
        this.serverIp=ip;
        this.serverPort=port;
        //客户端的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 requset=scanner.next();
            //2.构造请求对象,发送给服务器
            DatagramPacket requsetPacket=new DatagramPacket(requset.getBytes(),requset.getBytes().length,
                    InetAddress.getByName(serverIp),serverPort);
            socket.send(requsetPacket);
            //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 {
        UdpEchoClient udpEchoClient=new UdpEchoClient("127.0.0.1",9090);//127.0.0.1 本机ip
        udpEchoClient.start();

    }
}

运行结果如下
JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp
对上述过程中的一些谈论和分析:

JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp

JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp

JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp
JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp


多个客户端向一个服务器发送请求
JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp

JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp


JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp


下面写一个简单的翻译服务器
JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp

重写的服务器端的代码如下:

package network;

import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;

public class UdpDictServer extends UdpEchoServer{
    //使用HashMap保存中英文翻译的键值对
    private Map<String,String> dict =new HashMap<>();
    //实现父类的构造方法
    public UdpDictServer(int port) throws SocketException {
        super(port);

        //一些原始的键值对
        dict.put("cat","猫");
        dict.put("dog","狗");
        dict.put("people","人");
    }
    //与原始的UdpEachServer相比,这里对于请求的处理过程是不一样的
    //重写process方法

    @Override
    public String process(String request) {
        //找到对应的翻译,并返回
        //getOrDefault方法,找到key所对应的value值,如果没有找到,则返回defaultValue(即第二个参数)
        return dict.getOrDefault(request,"该词没有查询到");
    }

    public static void main(String[] args) throws IOException {
        UdpDictServer server=new UdpDictServer(9090);
        // start 不需要重新再写一遍了. 直接就复用了之前的 start
        server.start();
    }
}

执行结果如下:

JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp

JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp


JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp
JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp

JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp


下面写一个基于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;

//基于TCP的回显服务器
public class TcpEachServer {
    private ServerSocket serverSocket=null;

    //绑定端口号
    public  TcpEachServer(int port) throws IOException {
        serverSocket=new ServerSocket(port);
    }

    //启动服务器
    public  void  start() throws IOException {
        System.out.println("服务器开始启动");
        while(true){
            //从管理连接的队列中拿出一个“连接”出来
            Socket clientSocket=serverSocket.accept();
            //处理这个连接内的请求
            processConnection(clientSocket);
        }
    }
    //这个方法用来处理连接中的逻辑
    private void processConnection(Socket clientSocket) throws IOException {
        //日志
        System.out.printf("[%s:%d] 客户端上线\n",clientSocket.getInetAddress().toString(),
                clientSocket.getPort());
        //下面开始读取请求,计算响应,返回响应  三步曲
        //Socket对象内部包含两种字节流对象InputStream和OutputStream,可以先把这两个对象流获
        // 取到,方便后续处理过程种的读写工作
        try(InputStream inputStream=clientSocket.getInputStream();
            OutputStream outputStream=clientSocket.getOutputStream()){
            //不同于UDP协议中的无连接,在客户端的一次连接过程中,可能涉及多次请求/响应过程
            //因此。这里使用一个while循环,直到该连接中的所有请求处理完毕
            while(true){
                //1,读取请求并解析
                Scanner scanner=new Scanner(inputStream);
                //hasNext的作用是,检测输入流中是否有结束输入的控制符,比如0x1A(EOF,Ctrl-Z)
                //用于检测一个连接是否结束
                if(!scanner.hasNext()){
                    //一个连接处理完毕
                    System.out.printf("[%s:%d] 客户端本次连接处理完毕,下线!\n",clientSocket.getInetAddress().toString(),
                            clientSocket.getPort());
                    break;
                }
                // 这个代码暗含一个约定, 客户端发过来的请求, 得是文本数据, 同时, 还得带有空白符作为分割. (比如换行这种)
                //next():当输入到空白符结束
                String request=scanner.next();
                //2.根据请求计算响应
               String response=process(request);
               //3. 把响应写回客户端,把OutputStream用PrintWriter(此处的PrintWriter相当于Scanner)包裹一下,便于发送数据
                //将outputStream和PrintWriter关联起来
                PrintWriter writer=new PrintWriter(outputStream);
                //使用 PrintWriter 的 println 方法,打印到输出流中 把响应返回给客户端.
                //此处用 println, 而不是 print 就是为了在结尾加上 \n . 方便客户端读取响应, 使用 scanner.next 读取.
                writer.println(response);
                //这里还需要加一个 "刷新缓冲区" 操作.将缓冲区的数据强制输出,用于清空缓冲区
                writer.flush();

                //日志 记录当前的请求和响应
                System.out.printf("[%s:%d]  req: %s,resp: %s\n",clientSocket.getInetAddress().toString(),
                        clientSocket.getPort(),request,response);
            }
        }
    }

    //回显,只需要再返回这个字符串
    public String process(String requset){
        return requset;
    }
    public static void main(String[] args) throws IOException {
        TcpEachServer tcpEachServer=new TcpEachServer(9090);
        tcpEachServer.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;

    //服务器端的ip和port
    public  TcpEchoClient(String serverIp,int serverPort) throws IOException {
        //这个new的动作完成后,完成了tcp的建立
        socket=new Socket(serverIp,serverPort);
    }

    public void start() throws IOException {
        System.out.println("客户端启动");
        Scanner scannerConsole=new Scanner(System.in);
        //Socket对象内部包含两种字节流对象InputStream和OutputStream,可以先把这两个对象流获
        //   取到,方便后续处理过程种的读写工作
        try(InputStream inputStream=socket.getInputStream();
            OutputStream outputStream=socket.getOutputStream()){
            while(true){
                //1.从控制台输入字符串
                System.out.println("-->");
                String request=scannerConsole.next();
                //2.把请求发送给服务器  需要对request进行包装,使用PrintWriter
                PrintWriter printWriter=new PrintWriter(outputStream);
                //使用 println 带上换行. 后续服务器读取请求, 就可以使用 scanner.next 来获取了
                printWriter.println(request);//发送请求
                printWriter.flush();
                //3.从服务器中接收响应
                Scanner scannerNetwork=new Scanner(inputStream);
                String response=scannerNetwork.next();
                //4.把响应打印出来
                System.out.println(response);
            }
        }
    }
    public static void main(String[] args) throws IOException {
        TcpEchoClient tcpEchoClient=new TcpEchoClient("127.0.0.1",9090);
        tcpEchoClient.start();
    }
}

当开多个线程时,发现只有一个线程在被处理,其它线程都在等待,
JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp
当被处理的线程下线后,其他线程的逻辑才开始被处理
JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp

JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp
原因在于 Socket clientSocket = serverSocket.accept();和processConnection(clientSocket);都是主线程进行处理的且在同一次循环体中,只有一个clinetSocket连接被处理完后,才会去队列中accept下一个连接,为此,这里我们可以采用多线程进行处理。
JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp

修改为多线程后,可以看到 有多个客户端可以访问服务器
JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp

JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp
考虑到一个现实的情况,许多客户端需要频繁的访问服务器,那就是需要频繁的断开/连接,我们这里可以使用线程池
JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp
JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp
同样也可以实现多个客户端同时访问服务器。

最终的服务器的代码如下:

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;
//基于TCP的回显服务器
public class TcpEachServer {
    private ServerSocket serverSocket=null;
    //创建一个非固定数目的线程池
    private ExecutorService service= Executors.newCachedThreadPool();

    //绑定端口号
    public  TcpEachServer(int port) throws IOException {
        serverSocket=new ServerSocket(port);
    }

    //启动服务器
    public  void  start() throws IOException {
        System.out.println("服务器开始启动");
        while(true){
            //从管理连接的队列中拿出一个“连接”出来
            Socket clientSocket=serverSocket.accept();
            //处理这个连接内的请求
            service.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        processConnection(clientSocket);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
/*            Thread t=new Thread(() ->{
                try {
                    processConnection(clientSocket);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            t.start();*/
        }
    }
    //这个方法用来处理连接中的逻辑
    private void processConnection(Socket clientSocket) throws IOException {
        //日志
        System.out.printf("[%s:%d] 客户端上线\n",clientSocket.getInetAddress().toString(),
                clientSocket.getPort());
        //下面开始读取请求,计算响应,返回响应  三步曲
        //Socket对象内部包含两种字节流对象InputStream和OutputStream,可以先把这两个对象流获
        // 取到,方便后续处理过程种的读写工作
        try(InputStream inputStream=clientSocket.getInputStream();
            OutputStream outputStream=clientSocket.getOutputStream()){
            //不同于UDP协议中的无连接,在客户端的一次连接过程中,可能涉及多次请求/响应过程
            //因此。这里使用一个while循环,直到该连接中的所有请求处理完毕
            while(true){
                //1,读取请求并解析
                Scanner scanner=new Scanner(inputStream);
                //hasNext的作用是,检测输入流中是否有结束输入的控制符,比如0x1A(EOF,Ctrl-Z)
                //用于检测一个连接是否结束
                if(!scanner.hasNext()){
                    //一个连接处理完毕
                    System.out.printf("[%s:%d] 客户端本次连接处理完毕,下线!\n",clientSocket.getInetAddress().toString(),
                            clientSocket.getPort());
                    break;
                }
                // 这个代码暗含一个约定, 客户端发过来的请求, 得是文本数据, 同时, 还得带有空白符作为分割. (比如换行这种)
                //next():当输入到空白符结束
                String request=scanner.next();
                //2.根据请求计算响应
               String response=process(request);
               //3. 把响应写回客户端,把OutputStream用PrintWriter(此处的PrintWriter相当于Scanner)包裹一下,便于发送数据
                //将outputStream和PrintWriter关联起来
                PrintWriter writer=new PrintWriter(outputStream);
                //使用 PrintWriter 的 println 方法,打印到输出流中 把响应返回给客户端.
                //此处用 println, 而不是 print 就是为了在结尾加上 \n . 方便客户端读取响应, 使用 scanner.next 读取.
                writer.println(response);
                //这里还需要加一个 "刷新缓冲区" 操作.将缓冲区的数据强制输出,用于清空缓冲区
                writer.flush();

                //日志 记录当前的请求和响应
                System.out.printf("[%s:%d]  req: %s,resp: %s\n",clientSocket.getInetAddress().toString(),
                        clientSocket.getPort(),request,response);
            }
        } finally {
            clientSocket.close();
        }
    }

    //回显,只需要再返回这个字符串
    public String process(String requset){
        return requset;
    }
    public static void main(String[] args) throws IOException {
        TcpEachServer tcpEachServer=new TcpEachServer(9090);
        tcpEachServer.start();
    }
}


上述过程中的一些思路

JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp

JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp

JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp

JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp

JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp
JavaEE-网络编程套接字(UDP/TCP),Java-EE,网络,java-ee,udp文章来源地址https://www.toymoban.com/news/detail-728019.html


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

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

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

相关文章

  • UDP网络套接字编程

    先来说说数据在网络上的传输过程吧,我们知道系统其实终究是根据冯诺依曼来构成的,而网络数据是怎么发的呢? 其实很简单,网络有五层。如下: 如上图,我们知道的是,每层对应的操作系统中的那些地方,有些可能说是网络有七层,其实和这个五层一样的。下面我们

    2024年02月04日
    浏览(50)
  • 【JaveEE】网络编程之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月13日
    浏览(169)
  • 网络编程套接字(3)——Java数据报套接字(UDP协议)

    目录 一、Java数据报套接字通信模型 二、UDP数据报套接字编程 1、DatagramSocket         (1)DatagramSocket构造方法         (2)DatagramSocket方法 2、DatagramPacket         (1)DatagramPacket构造方法         (2)DatagramPacket方法 3、InetSocketAddress 三、代码示例:回显服务

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

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

    2024年02月05日
    浏览(65)
  • 【Linux】网络基础+UDP网络套接字编程

    只做自己喜欢做的事情,不被社会和时代裹挟着前进,是一件很奢侈的事。 1. 首先计算机是人类设计出来提高生产力的工具,而人类的文明绵延至今一定离不开人类之间互相的协作,既然人类需要协作以完成更为复杂的工作和难题,所以计算机作为人类的工具自然也一定需要

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

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

    2024年02月04日
    浏览(58)
  • 网络编程套接字(2): 简单的UDP网络程序

    3.1 服务端创建 (1) 创建套接字 create an endpoint for communication: 创建用于通信的端点 关于socket参数详细介绍: (1) domain: 指定套接字的通信域,相当于 struct sockaddr结构体的前16比特位(2字节) domain的选项是以宏的形式给出的,我们直接选用即可。常用就是上面框住的两个: AF_UNIX,本

    2024年02月10日
    浏览(56)
  • 【Linux网络】网络编程套接字(预备知识+UDP)

    目录 预备知识 1. 理解源IP地址和目的IP地址 2. 理解源MAC地址和目的MAC地址 3. 认识端口号  4. 理解源端口号和目的端口号 5. 端口号(port) vs 进程pid 6. 认识TCP协议和认识UDP协议 7. 网络字节序 socket编程接口  1. socket 常见API 2. sockaddr结构  简单的UDP网络程序  1. 服务端创建udp

    2024年02月19日
    浏览(58)
  • 【Linux Network】网络编程套接字(代码练习)—UDP

    目录 1. 常用接口 2. C/S 回声模拟 3. C/S myshell 的制作  Linux网络编程✨ 1. 常用接口 socket:创建套接字: 返回值: 套接字创建成功返回一个文件描述符 ,创建失败返回-1,同时错误码会被设置。 参数: domain: 网络通信 设置为 AF_INET(IPv4)或AF_INET6(IPv6) ; type:基于 UDP的网

    2024年02月03日
    浏览(96)
  • 【网络编程】详解UDP/TCP套接字的创建流程

    需要云服务器等云产品来学习Linux的同学可以移步/--腾讯云--/--阿里云--/--华为云--/官网,轻量型云服务器低至112元/年,新用户首次下单享超低折扣。   目录 一、网络编程套接字 1、一些概念 1.1源IP地址和目的IP地址 1.2端口号port 1.3TCP和UDP的性质 1.4网络字节序、IP地址类型转换

    2024年02月05日
    浏览(53)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包