java15-网络编程

news2024/11/29 10:46:12

一 网络编程概述

1.1 网络编程简介

        其实,所谓的网络编程,就是编写程序,实现让同一个网络中的机器实现数据的传递,实现通信。

        Java是 Internet 的语言,它从语言级上提供了对网络应用程序的支持。

        Java提供的网络类库,可以实现无痛的网络连接,联网的底层细节被隐藏在 Java 的本机安装系统里,由 JVM 进行控制,并且Java 实现了一个跨平台的网络库,因此程序员面对的是一个统一的网络编程环境,很容易开发常见的网络应用程序。

1.2 网络编程需要具备的条件

如果要实现两台机器之间实现通信,必须要满足几点要求:

1、需要知道对方的 IP 地址。

2 、需要知道对方的哪一个端口号来做数据的接受。

3 、通信的双方,需要遵循相同的通信协议。

1.3 IP地址和端口号的简介

1.3.1 IP地址

IP是 Internet Protocol (网络互连协议),在计算机中,使用IP地址来描述一个上网终端的唯一的地址编号。分为 IPv4 IPv6

IPv4 : 使用4个字节来描述一个IP地址,由四部分组成,每一部分一个字节。

IPv6 : 使用6个字节来描述一个IP地址,由六部分组成,每一部分一个字节。

IP 地址的分类:

A类: 1.0.0.1 ~ 126.255.255.254 :保留给政府机构

B类: 128.0.0.1 ~ 191.255.255.254 :分配给大中型企业

C类: 192.0.0.1 ~ 223.255.255.254 :分配给任何有需要的个人

D类: 224.0.0.1 ~ 239.255.255.254 :用于组播

E类: 240.0.0.1 ~ 255.255.255.254 :用于实验

1.3.2 端口号的简介

端口是设备与外界进行通信的数据的出口端口号的范围: [0,65535]

常见的端口占用:

3306: MySQL

1521 :Oracle

8080 :Tomcat

1.3.3InetAddress

java获取ip的代码演示:

 常用API之InetAddress
        1. 该类常用于描述一台机器ip和主机名信息
        2. 常用方法:
                static InetAddress getLocalHost()
                static InetAddress getByName(String hostname)
                String getHostAddress()
                String getHostName()

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;

public class _01InetAddressDemo {
    public static void main(String[] args) {

        try {
            // 获取一个描述本机信息的InetAddress对象: 包括主机名称和IP地址
            InetAddress localHost = InetAddress.getLocalHost();
            System.out.println(localHost);
            //获取里面的主机名称
            System.out.println("主机名称:"+localHost.getHostName());
            //获取里面的IP地址
            System.out.println("IP地址:"+localHost.getHostAddress());
            //IP的字节序列形式
            byte[] address = localHost.getAddress();
            System.out.println("IP的字节序列形式:"+ Arrays.toString(address));
            // 描述本机的形式有: 127.0.0.1 localhost 具体IP
            InetAddress a = InetAddress.getByName("127.0.0.1");
            System.out.println(a);

            InetAddress inet2 = InetAddress.getByName("www.baidu.com");
            System.out.println(inet2.getHostAddress());
            System.out.println(inet2.getHostName());
            // 获取域名对应的所有主机
            InetAddress[] allByName = InetAddress.getAllByName("www.baidu.com");
            System.out.println(allByName.length);
            for (InetAddress inetAddress : allByName) {
                System.out.println(inetAddress);
            }


        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}

1.4 通信协议

        常用的通信协议有:TCPUDPHTTP;而OSI模型过于理想化,未能在因特网上进行广泛推广,在这里章节,我们着重讲解一下TCP协议。

1.4.1 TCP协议

        是一个传输层的通信协议,是一个安全的,面向连接的通信协议。所谓的安全,指的是在数据传递的过程中,不会出现数据丢失的问题。 特点:安全的、面向连接

        TCP/IP 因其传输控制协议(TCP)和网络互联协议(IP)而得名。实际上是一组协议,其包含多个具有不同功能且互为关联的协议。

        TCP/IP协议模型从更实用的角度出发,形成了高效的四层体系结构,即网络接口层、IP层、传输层应用层。下图表示了TCP/IP的分层结构和与OSI参考模型的对应关系:

1.4.2 TCP的三次握手

        使用TCP实现数据在两个计算机之间进行传递,需要先在两个计算机之间建立一个安全的连接,然后再 通过这个连接,进行数据的传递。因此, TCP是一个安全的通信协议。

        在使用TCP进行数据传递的时候,存在两个角色,客户端和服务端。

        在TCP中,连接的建立过程会经历如下几个步骤:

        第一次握手

        建立连接时,由客户端向服务端发送一个 syn 包, syn包中是同步序列编号, 并进入SYN_SENT 状态,并等待服务器确认。

         第二次握手

        服务器收到了 syn 包,服务器必须确认客户端的syn,同时自己也发送一个syn包给客户端,即 SYN_ACK 包,并进入到 SYN_RECV 状态。 

        第三次握手

         客户端收到了服务端 SYN_ACK 包,并向服务端回复一个 ACK 包,此时客户端和服务端会进 入到TCP连接成功状态。 ESTABLISHED。

1.4.3 TCP与UDP的区别

运输层协议中有两个非常重要的协议:

  • 传输控制协议TCP(Transmission Control Protocol)

  • 用户数据报协议UDP(User Datagram Protocol)

        TCP是面向连接的运输层协议。即应用进程(或程序)在使用TCP协议之前,必须先建立TCP连接,在传输完毕后,释放已经建立的连接。利用TCP协议进行通信的两个应用进程,一个是服务器进程。另一个是客户进程。

        UDP是面向无连接的运输层协议。即应用进程(或程序)在使用UDP协议之前,不必先建立连接。自然,发送数据结束时也没有连接需要释放。因此,减少了开销和发送数据之前的时延。

二 TCP/IP程序编程

2.1 TCP/IP编程简介

2.1.1 C/S架构模型

        CS架构由客户端和服务器两个部分组成,通常采用C/S模式进行通信。其中,客户端负责向用户提供界面和交互功能,而服务器则负责存储和处理数据。在这种架构中,客户端和服务器之间通过网络进行通信,客户端向服务器发出请求,服务器响应并返回相应的结果。

        目前,CS架构已被广泛应用于各种场景中,如Web应用程序、电子邮件、数据库管理等,并且具有可扩展性、可靠性和安全性等优点。

        TCP利用Socket(套接字)接口来实现C/S模型的网络程序开发,其早已被广泛的采用。通常,主动发起通信的应用程序属于客户端。而服务器则是等待通信请求,当服务器收到客户端的请求,执行需要的运算然后向客户端返回结果。

        如我们使用QQ软件时,我们电脑上安装的就是一个客户端软件,而腾讯必需运行一个服务器。

2.1.2 Socket套接字介绍

        socket被称为套接字,用于描述IP地址和端口号主机上一般运行了多个服务软件,同时提供多种服务,每种服务都会打开一个Socket,并绑定到一个端口上,不同的端口对应不同的服务

        Socket和ServerSocket类位于java.net包中,ServerSocket用于服务端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,两个Socket构成一个通信管道。操作这个实例,完成所需要的通信。

套接字的基本操作有七个基本操作:

  1. 连接到远程主机

  2. 绑定到端口

  3. 接收从远程机器来的连接请求

  4. 监听到达的数据

  5. 发送数据

  6. 接收数据

  7. 关闭连接。

2.1.3 Socket编程步骤

套接字编程分为服务器编程和客户端编程,其通信模型如图所示:

 

1)服务端编程步骤如下:
  1. 调用 ServerSocket(int port) 创建一个服务器端套接字,并绑定到指定端口上。

  2. 调用 accept(),监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字。

  3. 调用 Socket类的 getOutputStream 和 getInputStream 获取输出流和输入流,开始网络数据的发送和接收。

  4. 最后关闭通信套接字。

演示代码:

TCP通信协议的服务端API
    1.ServerScoket 用来描述TCP的服务端
    2. 常用构造器:
        ServerSocket(int port): 用于指定一个端口号,返回具体实例
    3. 常用方法:
        setSoTimeout(int timeout): 用于定义服务端超时时间,单位是毫秒。超过指定时间,抛异常
        设置为0时,表示一直等待
        accept(): 一个阻塞方法,用于监听客户端的连接,如果监听到,则返回一个Socket对象。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class _02ServerSocketDemo {
    public static void main(String[] args) {
        //创建一个服务端的实例对象,指定端口号必须是没使用过的。
        try {
            ServerSocket server = new ServerSocket(9999);
            //设置超时时间,单位是毫秒。
//            server.setSoTimeout(10000);
            //调用accept方法监听客户端的连接: 是否连接服务器
            System.out.println("-----等待客户端连接,仅限十秒-----");
            Socket socket = server.accept();//如果制定了超时时间,该时间段内没有客户端连接,抛SocketTimeoutException
            System.out.println("-----一个客户端已经连接上了-----");
            //获取输入流,等待客户端传过来的信息
            System.out.println("-----等待客户端传过来的信息-----");
            InputStream inputStream = socket.getInputStream();
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(inputStream,"utf-8"));
            String s = br.readLine();
            System.out.println("服务端收到客户端的信息:"+s);

//            System.out.println("服务端IP: "+server.getInetAddress().getHostAddress());
//            System.out.println("服务端IP: "+server.getInetAddress().getHostName());
//            System.out.println("正在使用的端口号:"+server.getLocalPort());
//            System.out.println("详细信息:"+server.getLocalSocketAddress());
//            System.out.println("超时时间:"+server.getSoTimeout());
//            System.out.println("服务器绑定的端口是否是正确的:"+server.isBound());
//            System.out.println("服务端是否关闭:"+server.isClosed());

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
2)客户段编程步骤如下:
  1. 创建 Socket。根据指定的 IP和port构造 Socket 类对象,并发送连接请求。如服务器端响应,则建立客户端到服务器的通信线路。

  2. 通过Socket获取与服务器的通信流。 使用 getInputStream()方法获得输入流,使用 getOutputStream()方法获得输出流。

  3. 按照一定的协议对 Socket进行读/写操作。通过输入流读取服务端响应的信息,通过输出流将信息发送给服务端。

  4. 关闭 Socket。断开客户端到服务器的连接,释放线路。

代码演示:

TCP通信协议的客户端API
    1.Socket这个类用于描述TCP的客户端
    2. 常用构造器
        Socket(String host, int port): 指定要连接的服务器地址和端口号
        Socket(InetAddress host, int port): 指定要连接的服务器地址和端口号

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;

public class _03SocketDemo {
    public static void main(String[] args) {
        //指定服务器的IP和端口号,返回一个客户端的Socket对象,连接服务器
        try {
//            Socket socket = new Socket("127.0.0.1", 9999);
            Socket socket=new Socket(InetAddress.getByName("192.168.1.120"),9999);


//            System.out.println("-----客户端已经连接上了服务器-----");
            OutputStream out = socket.getOutputStream();
            PrintWriter pw = new PrintWriter(
                                new OutputStreamWriter(out,"Utf-8"),true);
            pw.println("你好,我是客户端,我现在非常开心,就像混凝土里面添加了爱情。");
            pw.println("爆发了詹姆斯传球勾股定理");
            System.out.println("发送完毕!");

            //测试客户端的其他方法
            InetAddress address = socket.getInetAddress();
            System.out.println("服务器地址"+address);
            InetAddress localAddress =socket.getLocalAddress();
            System.out.println("客户端地址"+localAddress);
            int localPort = socket.getLocalPort();
            System.out.println("客户端自己用于通信的端口号(系统分配的):"+localPort);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
3)流连接
  1. 客户端和服务器端的套接字对象诞生以后,必须进行输入、输出流的连接。

  2. 套接字调用 close()可以关闭双方的套接字连接,只要一方关闭连接,就会导致对方发生IOException异常。

三 聊天小项目

服务端代码部分:

package com.se.day12.chat1;

/*
    聊天服务器
 */

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class ChatServer {
    //定义一个TCP通信协议的服务端属性
    private ServerSocket server;
    // 添加一个Map属性,用于存储多个客户端的表示与输出流对象,Map集合(散列表)
    private Map<String,PrintWriter> allOut;


    public ChatServer(int port){
        try {
            server = new ServerSocket(port);
            // 给map集合赋值
            allOut = new HashMap<String,PrintWriter>();

        } catch (IOException e) {
            System.out.println("----------服务器启动失败-----------");
        }
    }
    public void start(){

        try {
            while(true){
                System.out.println("---等待客户端连接---");
                Socket socket = server.accept();
                System.out.println("---一个客户端连接成功---");

                // 没获取一个客户端的socket对象,就应该将其放入一个并发线程中
                getClientInfoHandler getClientInfoHandler = new getClientInfoHandler(socket);
                Thread thread = new Thread(getClientInfoHandler);
                thread.start();
            }


        } catch (IOException e) {
            System.out.println("---一个客户端连接超时---");
        }
    }

    public static void main(String[] args) {
        // 创建一个具体的服务器对象
        ChatServer chatServer = new ChatServer(8848);
        //调用聊天的主方法
        chatServer.start();

    }

    /*
        定义一个处理客户端信息的处理器,即一个任务体
     */
    class getClientInfoHandler implements Runnable{
        // 因为run方法中使用了start方法中的socket局部变量
        // 所以可以在该类中添加一个属性,run方法中可以访问该类的属性
        private Socket socket;
        // 提供一个构造器,将start方法中的局部变量socket传进来,给属性赋值,这样run方法中使用的socket就是
        //start方法中的局部变量指向的对象。
        public getClientInfoHandler(Socket socket) {
            this.socket = socket;
        }

        public void run() {
            String nickname = null;
            try {
                //通过服务端的Socket对象获取输入流,读取客户端发送过来的信息
                InputStream inputStream = socket.getInputStream();
                BufferedReader br = new BufferedReader(
                                    new InputStreamReader(inputStream,"utf-8"));
                // 通过服务端的Socket对象,获取输出流,将信息返回给客户端
                OutputStream outputStream = socket.getOutputStream();
                PrintWriter pw = new PrintWriter(
                                    new OutputStreamWriter(outputStream,"utf-8"),true);
                //先获取客户端的昵称
                nickname = br.readLine();
                //判断昵称是否重复,如果已经被占用,加后缀
                while(allOut.containsKey(nickname)){
                    nickname = nickname+"_"+System.currentTimeMillis();
                }
                // 将昵称告诉客户端
                pw.println(nickname);
                // 将输出流添加到Map集合中
                allOut.put(nickname,pw);
                System.out.println("-------在线人数: " +allOut.size()+"人------");


                // 循环打印客户端发送的信息
                String info = "";
                while((info = br.readLine())!=null){
                    if (info.startsWith("@")){
                        //私聊
                        sendPrivateInfo(nickname,info);
                    }else {
                        //将信息info发送到所有的客户端里
                        sendToAllClient(nickname,info);
                    }
                }
            } catch (Exception e) {
                System.out.println("---一个客户端离线了---");
                // 删除队友的键值对儿
                allOut.remove(nickname);
                System.out.println("-------在线人数: " +allOut.size()+"------");

            }
        }
//        public void sendPrivateInfo(String nickname,String info){
//            String[] split = info.split(":");
//            split[0]=split[0].substring(1);
//            if(allOut.containsKey(split[0])){
//                allOut.get(nickname).println("你悄悄对"+split[0]+"说:"+split[1]);
//                allOut.get(split[0]).println(nickname+"悄悄对你说:"+split[1]);
//            }else {
//                allOut.get(nickname).println("该用户不在线");
//            }
//
//        }
        public void sendPrivateInfo(String nickname,String info){
            String s1 = info.substring(1, info.indexOf(":"));
            String s2 = info.substring(info.indexOf(":")+1);
            if(allOut.containsKey(s1)){
                allOut.get(nickname).println("你悄悄对"+s1+"说:"+s2);
                allOut.get(s1).println(nickname+"悄悄对你说:"+s2);
            }else {
                allOut.get(nickname).println("该用户不在线");
            }

        }

        public void sendToAllClient(String nickname,String info){
            // 遍历Map里的所有输出流,来发送info信息
            Set<String> nicks = allOut.keySet();
            for(String nick:nicks){
                // 获取对应的输出流,然后发送信息
                allOut.get(nick).println(nickname+"说:"+info);
            }
        }

    }

}

 客户端代码部分:

package com.se.day12.chat1;

/*
    聊天客户端
 */

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

public class ChatClient {
    //定义一个TCP通信协议的客户端属性
    private Socket socket;
    public ChatClient(){
        //获取socket对象,同时向服务端发送连接请求,连接失败,Connection refused
        try {
            socket = new Socket("localhost",8848);
        } catch (IOException e) {
            System.out.println("---服务器崩溃---");
        }
    }
    //聊天的启动方法
    public void start() {
        try {
            // 获取一个获取服务端信息的处理器任务
            Runnable task = new GetServerInfoHandler();
            // 创建一个线程对象
            Thread thread = new Thread(task);
            thread.start();

            //获取向服务器发送信息的的输出流对象
            OutputStream os = socket.getOutputStream();
            // 封装成字符缓存流,可以按行输出
            PrintWriter pw = new PrintWriter(
                    new OutputStreamWriter(os,"Utf-8"),
                    true);
            //使用控制台扫描对象类型,不断地扫描控制台上的文字
            Scanner scan = new Scanner(System.in);
            //先设置昵称
            System.out.println("请输入您的昵称:");
            String nickname = scan.nextLine();
            // 将昵称发送给服务器,让服务器校验昵称是否已经被占用
            pw.println(nickname);

            System.out.println("===开始聊天===");
            while(true){
                String s = scan.nextLine();
                //将扫描的信息发送到服务端
                pw.println(s);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    public static void main(String[] args) {
        //创建一个具体的聊天客户端  对象
        ChatClient chatClient = new ChatClient();
        //调研客户端的主方法
        chatClient.start();
    }

    /*
        编写一个获取服务端信息的处理器。即一个任务体
     */

    class GetServerInfoHandler implements Runnable{
        @Override
        public void run() {
            try {
                // 获取接收服务端发送过来的数据的输入流对象
                InputStream is = socket.getInputStream();
                BufferedReader br = new BufferedReader(
                        new InputStreamReader(is,"utf-8"));
                //获取自己的昵称:
                String nickname = br.readLine();
                System.out.println("您的昵称为:"+nickname);

                String line = "";
                while((line = br.readLine())!=null){
                    System.out.println(line);
                }
            } catch (Exception e) {
               e.printStackTrace();
            }
        }
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2059959.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

注册Github账号详细过程

目录 一、准备工作 二、注册步骤 一、准备工作 在注册GitHub账号之前&#xff0c;请确保您已经准备好以下信息&#xff1a; 一个有效的电子邮箱地址&#xff1a;用于接收验证邮件和GitHub的后续通知。 用户名&#xff1a;确保该用户名在GitHub上是唯一的&#xff0c;且符合…

如何选择合适的端口管控软件

一、明确需求 管控的端口类型&#xff1a;首先确定需要管控的端口类型是USB端口&#xff0c;还是需要同时管控串口、并口等其他类型的端口。 管控的力度&#xff1a;确定是需要对所有端口进行统一管控&#xff0c;还是需要根据不同的用户或部门实施不同的策略。 日志记录需求…

图神经网络教程1-综述

目录 前言 介绍 贡献 分类 预备知识 学习方式 转导式学习 归纳学习 系列文章列表 前言 翻译自A Practical Tutorial on Graph Neural Networks&#xff0c;并给出详细的解释和注意事项以及个人的思考&#xff0c;原作者如下&#xff1a; 介绍 当代人工智能(AI)&#x…

最佳实践:CI/CD交付模式下的运维展望丨IDCF

李洪锋 启迪万众数字技术(广州)有限公司 &#xff0c;产品研发中心-系统运维部、研发效能&#xff08;DevOps&#xff09;工程师&#xff08;中级&#xff09;课程学员 一、DevOps现状 据云计算产业联盟《中国DevOps现状调查报告2023》显示&#xff0c;国内DevOps 落地成熟度…

JUC阻塞队列(四):DelayQueue

1、DelayQueue介绍 DelayQueue 是一个延迟队列&#xff0c;生产者写入一个数据&#xff0c;这个数据具有被直接消费的延迟时间&#xff0c; 让数据具有延迟的特性。 DelayQueue底层也是基于二叉堆来实现的&#xff0c;DelayQueue本就是基于PriorityBQueue 实现的。 二叉堆结构每…

NCL画出来的图模糊问题处理

问题介绍&#xff1a; 如图所示&#xff0c;NCL画出来的图分辨率比较低&#xff0c;图片比较模糊&#xff0c;怎么将分辨率提高&#xff1f; 解决方法&#xff1a; ; 采用这个方法来定义wkswks_type "png"wks_typewkWidth 2500wks_typewkHeight 2500wks gsn_…

网易、网易互娱、360、头条、商汤等公司面试真题....

测试岗/测试开发岗面试真题 来源与网易、网易互娱、360、头条、商汤等公司面试真题 自我介绍 项目中负责什么? 团队几个人&#xff1f;合作情况 为什么要读研 项目/实习介绍 项目中负责什么? 团队几个人&#xff1f;合作情况 项目的方法怎么改进&#xff0c;和别人方…

微信为什么会限制加好友?

微信限制加好友主要是为了防止垃圾信息和滥用行为&#xff0c;包括以下几个原因&#xff1a; 1、防止骚扰&#xff1a;限制加好友可以减少陌生人骚扰和垃圾广告。 2、保护用户隐私&#xff1a;控制好友请求能更好地保护用户的个人信息。 3、提升用户体验&#xff1a;避免用户…

用博达网站群管理平台设计网站时如何创建二级导航

1 介绍 现用博达网站群管理平台设计出的网站只能一级导航&#xff0c;亦即点击首页的顶端导航&#xff0c;直接出现列表页&#xff0c;无法出现二级菜单。二级菜单在网站开发中被称为二级导航。 怎样用博达网站群管理平台制作出二级导航的效果&#xff1f;这个问题在《网站群…

掌握电子邮件的艺术:使用 Mailbird 统一管理您的数字生活

在数字时代&#xff0c;电子邮件已成为我们沟通的骨干。无论是商务交流、家庭联络&#xff0c;还是订阅更新&#xff0c;我们几乎每天都在使用电子邮件。但随着账户数量的增加&#xff0c;管理这些账户变得日益复杂。如何有效地整合和优化您的电子邮件体验&#xff1f;Mailbird…

Arduino调试ESP32常见问题 exit status 1

问题1&#xff1a;代码上传&#xff08;烧录&#xff09;报Failed uploading: uploading error: exit status 1大概率原因&#xff1a;没有安装对应的驱动&#xff0c;我的ESP32驱动是CH340点击这里下载CH340 下载后打开&#xff0c;若出现乱码不用在意&#xff0c;点击第一个按…

原生js实现下滑到当前模块进度条填充

<div style"height: 1500px;"></div> <div class"progress-container"><div class"progress-bar" data-progress"90%"><p class"progress-text">Google Ads在Google搜索引擎上覆盖超过90%的互…

浙江大学蒋超实验室在JHM发文揭示日常使用量的一次性纸杯释放的微塑料或可能影响孕期健康

CQ师姐做的一个纸杯微塑料项目&#xff0c;非常有意思&#xff0c;揭示了日常生活中真实来源的孕期微塑料暴露&#xff0c;对生殖和代谢性能的影响和调控机制。我参与了其中的部分实验和分析&#xff0c;学习了养小鼠&#xff0c;灌胃&#xff0c;解剖和部分塑料的定性定量等实…

二、Socket链接方式分类

一、Socket通信基本流程图 1、流程图 2、链接方式 &#xff08;1&#xff09;同步 商业中不会用&#xff0c;会有阻塞的情况出现&#xff1b;举例&#xff1a; 客户端的玩家升级&#xff0c;向服务器发送这条信息&#xff0c;而服务器传输回来需要一定时间&#xff0c;此时…

探索《黑神话:悟空》品质保障的背后:ISO体系认证

《黑神话&#xff1a;悟空》横空出世 8月20日上午10点&#xff0c;国产首款大型3A游戏《黑神话&#xff1a;悟空》正式上线。游戏一经上线便吸引了无数国内外用户的关注&#xff0c;不仅仅是因为其高超的游戏制作技术&#xff0c;极高的画面精度&#xff0c;精良的的视觉和战斗…

如何将平淡无奇的产品推向市场?借助ChatGPT,仅需3秒即可化身短视频创意策划大师,助你的产品一夜成名!

本文通过一系列生动的实例&#xff0c;展示了如何通过ChatGPT生成创意和独特的宣传方式&#xff0c;将平凡或不起眼的产品转化为市场上的明星。从全红婵最爱的小乌龟到棋牌室排烟机&#xff0c;再到食物研磨器的成功案例&#xff0c;我们可以看到&#xff0c;创意和创新的宣传策…

手把手教你如何注册使用Runway Gen3,10秒搞定专业级视频制作

大家好&#xff01;我是YUAN。 今天&#xff0c;我们要介绍的是一款AI视频制作的王者级工具——Runway Gen-3。它不仅能够在短时间内生成高质量的视频&#xff0c;还能满足不同风格和场景的需求。 一、Runway Gen-3是什么&#xff1f; Runway Gen-3是一款功能强大的AI视频生…

jenkins最佳实践(二):Pipeline流水线部署springCloud微服务项目

各位小伙伴们大家好呀&#xff0c;我是小金&#xff0c;本篇文章我们将介绍如何使用Pipeline流水线部署我们自己的微服务项目&#xff0c;之前没怎么搞过部署相关的&#xff0c;以至于构建流水线的过程中中也遇到了很多自己以前没有考虑过的问题&#xff0c;特写此篇&#xff0…

水凝胶结机器人咋自主运动?利用拓扑调用的自我调节!

大家好&#xff0c;今天我们来聊聊一项有趣的研究 —— 水凝胶结机器人。这篇文章《Animating hydrogel knotbots with topology-invoked self-regulation》发表于《Nature Communications》。想象一下&#xff0c;小小的机器人能够像生物一样自主运动&#xff0c;这是不是很神…

极空间Z4Pro,最懂中国人的NAS,为了极影视值得入手

极空间Z4Pro&#xff0c;最懂中国人的NAS&#xff0c;为了极影视值得入手 小伙伴们大家好&#xff0c;我的极空间Z4Pro是在首发的时候交定金购买的&#xff0c;到目前为止也算是用了很长一段时间了&#xff0c;说一下自己的使用体验吧。 首先是这个极空间的外观&#xff0c;并…