IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 网络编程套接字 -> 正文阅读

[网络协议]网络编程套接字

作者:token comment

socket简介

在这里插入图片描述

TCP和UDP直观区别

在这里插入图片描述

UDP实现回显服务

在这里插入图片描述

服务器端

代码简易实现

package network;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;

/**
 * @author: fs
 * @date: 2022/4/22 15:49
 * @Description:
 */
//服务器端
public class UdpEchoServer {
    //进行网络编程,第一步就需要先准备好 socket 实例~这是进行网络编程的大前提.
    private DatagramSocket socket=null;

    public UdpEchoServer(int port) throws SocketException {
        socket=new DatagramSocket(port);
    }

    //启动服务器
    public void start() throws IOException {
        System.out.println("启动服务器!");
        // UDP不需要建立连接,直接接收从客户端来的数据即可
        while(true){
            //1.读取客户端发来的请求
            DatagramPacket requestPacket = new DatagramPacket(new byte[1024],1024);
            socket.receive(requestPacket);//为了接受数据,需要先准备好一个空的DatagramPacket对象,由 receive来进行填充数据
            //将DatagramPacket解析成一个字符串
            String request=new String(requestPacket.getData(),0,requestPacket.getLength());

            //2.根据请求计算响应(由于咱们这是一个回显服务,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 server=new UdpEchoServer(9090);
        server.start();
    }
}

代码说明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

客户端

代码实现

package network;


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;

/**
 * @author: fs
 * @date: 2022/4/22 15:49
 * @Description:
 */
//客户端角度:
    //站在客户端的角度:
    //源IP:本机 IP
    //源端口:系统分配的端口
    // 目的IP:服务器的IP
    // 目的端口:服务器的端口
    // 协议类型:UDP
public class UdpEchoClient {
    private DatagramSocket socket=null;
    private String serverIP;
    private int serverPort;

    public  UdpEchoClient(String ip,int port)throws SocketException{
        //此处的port是服务器端口
        //客户端启动的时候,不需要给 socket 指定端口.客户端自己的端口是系统随机分配的
        socket=new DatagramSocket();
        serverIP=ip;
        serverPort=port;
    }

    public void start() throws IOException {
        Scanner scanner=new Scanner(System.in);
        while(true){
            // 1.先从控制台读取用户输入的字符串
            System.out.println("-> ");
            String request=scanner.next();
            //2.把这个用户输入的内容,构造成一个UDP请求,并发送.
//            构造的请求里包含两部分信息:
//            1)数据的内容 request 字符串
//            2)数据要发给谁~ 服务器的IP+端口

            DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length,
                    InetAddress.getByName(serverIP),serverPort);
            socket.send(requestPacket);
            //3.从服务器读取响应数据,并解析
            DatagramPacket responsePacket = new DatagramPacket(new byte[1024],1024);
            socket.receive(responsePacket);
            String response=new String(responsePacket.getData(),0,responsePacket.getLength(),"UTF-8");
            //4.把响应结果显示到控制台上.
            System.out.printf("req: %s,resq: %s \n",request,response);
        }
    }

    public static void main(String[] args) throws IOException {
        //由于服务器和客户端在同一个机器上,使用的 IP仍然是 127.0.0.1.如果是在不同的机器上,当然就需要更改这里的IP了
        UdpEchoClient client=new UdpEchoClient("127.0.0.1",9090);
        client.start();
    }

}

代码说明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

重写process实现翻译查询

在这里插入图片描述

package network;

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

/**
 * @author: fs
 * @date: 2022/4/22 20:21
 * @Description:
 */
public class UdpDictServer extends UdpEchoServer{
    private HashMap<String, String> dict = new HashMap<>();
    public UdpDictServer(int port) throws SocketException {
        super(port);
        dict.put( "cat","小猫");
        dict.put("dog","小狗");
        dict.put("fuck","卧槽");
        dict.put("pig","小猪");
    }
        @Override
        public String process(String request) {
            return dict.getOrDefault(request, "该词无法被翻译!");
        }

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

注意!

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

TCP

服务器端代码

package TCPnetwork;

import UDPnetwork.UdpDictServer;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

/**
 * @author: fs
 * @date: 2022/4/22 22:35
 * @Description:
 */
public class TcpEchoServer {
    // listen =>英文原意监听~~
    //但是在Java socket中是体现不出来“监听”的含义的~~
    //之所以这么叫,其实是操作系统原生的API里有一个操作叫做listenl
    // private ServerSocket listenSocket = null;
    private ServerSocket serverSocket=null;

    public TcpEchoServer(int port) throws IOException {
        serverSocket=new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
        while(true){
            //由于 TCP是有连接的,不能一上来就读数据,而要先建立连接.(接电话)
            //accept就是在“"接电话",接电话的前提是,有人给你打了~~,如果当前没有客户端尝试建立连接,此处的 accept就会阻塞.
            //accept 返回了一个 socket对象,称为 clientSocket,后续和客户端之间的沟通,都是通过clientSocket 来完成的.
            //进一步讲,serverSocket就干了一件事,接电话~~

            Socket clientSocket=serverSocket.accept();
            ProcessConnection(clientSocket);
        }
    }

    private void ProcessConnection(Socket clientSocket) {
        System.out.printf("[%s:%d] 客户端连接建立!",clientSocket.getInetAddress().toString(),clientSocket.getPort());
        //接下来来处理请求和响应
        //这里的针对TCP socket的读写就和文件读写是一模一样的!!
        try(InputStream inputStream=clientSocket.getInputStream()){
            try(OutputStream outputStream=clientSocket.getOutputStream()){
                //循环处理每个请求,分别返回响应
                Scanner scanner=new Scanner(inputStream);
                while(true){
                    //1读取请求
                    if(!scanner.hasNext()){
                        System.out.printf("[%s:%d] 客户端断开连接!\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());
                        break;
                    }
                    //此处用Scanner更方便.如果不用Scanner就用原生的 InputStream的 read 也是可以的
                    String request=scanner.next();
                    //2根据请求计算响应
                    String response=process(request);
                    //3.把这个响应返回给客户端
                    //为了方便起见,可以使用 PrintWriter把 outputStream 包裹一下
                    PrintWriter printWriter=new PrintWriter(outputStream);

                    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) {
            e.printStackTrace();
        }finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public String process(String request) {
        return request;
    }

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

处理多个连接

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

多线程处理

在这里插入图片描述

在这里插入图片描述

代码实现

package TCPnetwork;

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;

/**
 * @author: fs
 * @date: 2022/4/23 19:48
 * @Description:
 */
public class TcpThreadEchoServer {
    // listen =>英文原意监听~~
    //但是在Java socket中是体现不出来“监听”的含义的~~
    //之所以这么叫,其实是操作系统原生的API里有一个操作叫做listenl
    // private ServerSocket listenSocket = null;
    private ServerSocket serverSocket=null;

    public TcpThreadEchoServer(int port) throws IOException {
        serverSocket=new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
        while(true){
            //由于 TCP是有连接的,不能一上来就读数据,而要先建立连接.(接电话)
            //accept就是在“"接电话",接电话的前提是,有人给你打了~~,如果当前没有客户端尝试建立连接,此处的 accept就会阻塞.
            //accept 返回了一个 socket对象,称为 clientSocket,后续和客户端之间的沟通,都是通过clientSocket 来完成的.
            //进一步讲,serverSocket就干了一件事,接电话~~
            Socket clientSocket=serverSocket.accept();
            //[改进方法]在这个地方,每次 accept成功,都创建一个新的线程,由新线程负责执行这个 processConnection方法~
            Thread t=new Thread(()->{
                ProcessConnection(clientSocket);
            });
            t.start();
        }
    }

    private void ProcessConnection(Socket clientSocket) {
        System.out.printf("[%s:%d] 客户端连接建立!",clientSocket.getInetAddress().toString(),clientSocket.getPort());
        //接下来来处理请求和响应
        //这里的针对TCP socket的读写就和文件读写是一模一样的!!
        try(InputStream inputStream=clientSocket.getInputStream()){
            try(OutputStream outputStream=clientSocket.getOutputStream()){
                //循环处理每个请求,分别返回响应
                Scanner scanner=new Scanner(inputStream);
                while(true){
                    //1读取请求
                    if(!scanner.hasNext()){
                        System.out.printf("[%s:%d] 客户端断开连接!\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());
                        break;
                    }
                    //此处用Scanner更方便.如果不用Scanner就用原生的 InputStream的 read 也是可以的
                    String request=scanner.next();
                    //2根据请求计算响应
                    String response=process(request);
                    //3.把这个响应返回给客户端
                    //为了方便起见,可以使用 PrintWriter把 outputStream 包裹一下
                    PrintWriter printWriter=new PrintWriter(outputStream);

                    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) {
            e.printStackTrace();
        }finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    private String process(String request) {
        return request;
    }

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

}

线程池的代码实现

package TCPnetwork;

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;

/**
 * @author: fs
 * @date: 2022/4/23 21:32
 * @Description:
 */
public class TcpThreadPollEchoServer {
    // listen =>英文原意监听~~
    //但是在Java socket中是体现不出来“监听”的含义的~~
    //之所以这么叫,其实是操作系统原生的API里有一个操作叫做listenl
    // private ServerSocket listenSocket = null;
    private ServerSocket serverSocket=null;

    public TcpThreadPollEchoServer(int port) throws IOException {
        serverSocket=new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
        ExecutorService pool= Executors.newCachedThreadPool();
        while(true){
            //由于 TCP是有连接的,不能一上来就读数据,而要先建立连接.(接电话)
            //accept就是在“"接电话",接电话的前提是,有人给你打了~~,如果当前没有客户端尝试建立连接,此处的 accept就会阻塞.
            //accept 返回了一个 socket对象,称为 clientSocket,后续和客户端之间的沟通,都是通过clientSocket 来完成的.
            //进一步讲,serverSocket就干了一件事,接电话~~
            Socket clientSocket=serverSocket.accept();
            //[改进方法]在这个地方,每次 accept成功,都创建一个新的线程,由新线程负责执行这个 processConnection方法~
            //通过线程池来实现
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    ProcessConnection(clientSocket);
                }
            });

        }
    }

    private void ProcessConnection(Socket clientSocket) {
        System.out.printf("[%s:%d] 客户端连接建立!",clientSocket.getInetAddress().toString(),clientSocket.getPort());
        //接下来来处理请求和响应
        //这里的针对TCP socket的读写就和文件读写是一模一样的!!
        try(InputStream inputStream=clientSocket.getInputStream()){
            try(OutputStream outputStream=clientSocket.getOutputStream()){
                //循环处理每个请求,分别返回响应
                Scanner scanner=new Scanner(inputStream);
                while(true){
                    //1读取请求
                    if(!scanner.hasNext()){
                        System.out.printf("[%s:%d] 客户端断开连接!\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());
                        break;
                    }
                    //此处用Scanner更方便.如果不用Scanner就用原生的 InputStream的 read 也是可以的
                    String request=scanner.next();
                    //2根据请求计算响应
                    String response=process(request);
                    //3.把这个响应返回给客户端
                    //为了方便起见,可以使用 PrintWriter把 outputStream 包裹一下
                    PrintWriter printWriter=new PrintWriter(outputStream);

                    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) {
            e.printStackTrace();
        }finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    private String process(String request) {
        return request;
    }

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

重写翻译查询语句代码实现

package TCPnetwork;

import UDPnetwork.UdpDictServer;

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

/**
 * @author: fs
 * @date: 2022/4/23 21:41
 * @Description:
 */
public class TcpDictServer extends TcpEchoServer{
    private HashMap<String, String> dict = new HashMap<>();
    public TcpDictServer(int port) throws IOException {
        super(port);
        dict.put( "cat","小猫");
        dict.put("dog","小狗");
        dict.put("fuck","卧槽");
        dict.put("pig","小猪");
    }

    @Override
    public String process(String request) {
        return dict.getOrDefault(request, "该词无法被翻译!");
    }

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

客户端代码

    package TCPnetwork;

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.security.spec.PSSParameterSpec;
    import java.util.Scanner;

    /**
     * @author: fs
     * @date: 2022/4/22 23:06
     * @Description:
     */
    public class TcpEchoClient {
        //用普通的 socket即可,不用 ServerSocket 了
        // 此处也不用手动给客户端指定端口号,让系统自由分配.

        private Socket socket=null;

        public TcpEchoClient(String serverIP,int serverPort) throws IOException {
            //其实这里是可以给的.但是这里给了之后,含义是不同的,~~
            //这里传入的ip和端口号的含义表示的不是自己绑定,而是表示和这个ip端口建立连接!!
            // 调用这个构造方法,就会和服务器建立连接(打电话拨号了)
            socket=new Socket(serverIP,serverPort);
        }

        public void start(){
            System.out.println("服务器连接成功!\n");
            Scanner scanner=new Scanner(System.in);
            try(InputStream inputStream=socket.getInputStream()) {
                try (OutputStream outputStream = socket.getOutputStream()) {
                    while(true){
                        //要做的事情,仍然是四个步骤
                        // 1.从控制台读取字符串
                        System.out.println("-> ");
                        String request=scanner.next();
                        //2.根据读取的字符串,构造请求,把请求发给服务器
                        PrintWriter printWriter=new PrintWriter(outputStream);
                        printWriter.println(request);
                        printWriter.flush();//如果不刷新,可能服务器无法看到数据
                        // 3.从服务器读取响应,并解析
                        Scanner respScanner=new Scanner(inputStream);
                        String response=respScanner.next();
                        //4.把结果显示到控制台上.
                        System.out.printf("req: %s , resp: %s \n",request,response);
                    }
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }

        public static void main(String[] args) throws IOException {
            TcpEchoClient tcpEchoClient=new TcpEchoClient("127.0.0.1",9090);
            tcpEchoClient.start();
        }
    }
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-04-26 12:12:37  更:2022-04-26 12:14:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:27:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码