网络编程---Java飞机大战联机

news2025/6/24 19:59:44

解析服务器端代码

代码是放在app/lib下的src下的main/java,而与之前放在app/src/main下路径不同

Main函数

Main函数里只放着创建MyServer类的一行

public static void main(String args[]){
        new MyServer();
    }

MyServer构造函数

1.获取本机IP地址

//获取本机IP地址
            InetAddress addr = InetAddress.getLocalHost();
            System.out.println("local host:" + addr);

2.创建serverSocket(创建服务器套接字并绑定到一个端口上)

//创建server socket
            ServerSocket serverSocket = new ServerSocket(9999);
            System.out.println("listen port 9999");

3.accept方法监听等待

//等待客户端连接
            while(true){
                System.out.println("waiting client connect");
                //从连接请求队列中取出一个客户的连接请求,然后创建与客户连接的Socket对象,并将它返回
                // 如果队列中没有连接请求,accept()方法就会一直等待,直到接收到了连接请求才返回
                Socket socket = serverSocket.accept();
                //连接成功,返回socket对象
                System.out.println("accept client connect" + socket);
                new Thread(new Service(socket)).start();
            }

4.监听成功,创建线程进行通信(上一步while循环内最后一行)

创建线程进行通信

  • 线程构造函数内,new数据传输通道
 class Service implements Runnable{
        private Socket socket;
        private BufferedReader in = null;

        public Service(Socket socket){
            this.socket = socket;
            try{
                //InputStreamReader把字节流转化成字符流
                //BufferedReader用于读取字符流。它继承自Reader类,提供了按行读取文件的功能
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            }catch (IOException ex){
                ex.printStackTrace();
            }
        }
  • 重写的run函数内,用一个while来不断读入客户端传来的流(用BufferedReader)
@Override
        public void run() {
            System.out.println("wait client message " );
            try {
                while ((content = in.readLine()) != null) {
                    //从socket连接读取到bye标识客户端发出断开连接请求
                    if(content.equals("bye")){
                        System.out.println("disconnect from client,close socket");
                        //关闭socket输入输出流
                        socket.shutdownInput();
                        socket.shutdownOutput();
                        socket.close();   //关闭socket连接
                        break;
                    }else {
                        //从socket连接读取到的不是断开连接请求,则像客户端发信息
                        this.sendMessge(socket);
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
  • 如何sendMessage:用PrintWriter
public void sendMessge(Socket socket) {
            PrintWriter pout = null;
            try{
                String message = "hello,client!";
                System.out.println("messge to client:" + message);

                //OutputStreamWriter:将字符流转换为字节流
                //BufferedWriter:是缓冲字符输出流
                //PrintWriter:字符类型的打印输出流
                pout = new PrintWriter(new BufferedWriter(
                        new OutputStreamWriter(socket.getOutputStream(),"utf-8")),true);
                //利用输出流输出数据
                pout.println(message);

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

解析客户端代码

1.与服务器的连接

NetConn netConn = new NetConn(handler);

2.与服务器的信息交流

其中的writer在与服务器进行连接会把它进行赋值,它是获得了socket输出流的PrintWriter,把信息给到服务器。(注:接收服务器的信息是在netConn线程的run方法里用了一个while)

new Thread(){
                @Override
                public void run(){
                    Log.i(TAG, "send message to server");
                        writer.println("hello,server");
                }
            }.start();

NetConn是一个线程

在重写的 run 方法里

1.创建socket并连接对象

//创建socket对象
                socket = new Socket();
                //connect,要保证服务器已启动
                socket.connect(new InetSocketAddress
                        ("10.0.2.2",9999),5000);

2.获取socket的输入输出流

//获取socket输入输出流
                in = new BufferedReader(new InputStreamReader(socket.getInputStream(),"utf-8"));
                writer = new PrintWriter(new BufferedWriter(
                        new OutputStreamWriter(
                                socket.getOutputStream(),"utf-8")),true);
                Log.i(TAG,"connect to server");

3.再建一个线程,接收服务器的数据

//接收服务器返回的数据
                Thread receiveServerMsg =  new Thread(){
                    @Override
                    public void run(){
                        String fromserver = null;
                        try{
                            while((fromserver = in.readLine())!=null)
                            {
                                //发送消息给UI线程
                                Message msg = new Message();
                                msg.what = 1;
                                msg.obj = fromserver;
                                toClientHandler.sendMessage(msg);
                            }
                        }catch (IOException ex){
                            ex.printStackTrace();
                        }
                    }
                };

感觉hander像个快递员???把在服务器接收数据线程里,接收到的东西,打包成message,通过sendMessage函数,发给UI线程(就是那些Activity),进行相应操作。

以下是MainActivity内的Handler

handler = new Handler(Looper.getMainLooper()){
            //当数据处理子线程更新数据后发送消息给UI线程,UI线程更新UI
            @Override
            public void handleMessage(Message msg){
                if(msg.what == 1){
                    txt.setText(msg.obj.toString());
                }
            }
        };

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

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

相关文章

上网行为管理的作用是什么?有哪些上网行为管理软件?

上网行为管理在现代企业及家庭环境中扮演着至关重要的角色,其作用不仅限于提升网络安全性,还涉及保护企业信息安全、提高员工工作效率等多个方面。以下将详细阐述上网行为管理的作用,并介绍几款主流的上网行为管理软件。 一、上网行为管理的作…

CANoe连接Option Scope使用方法

系列文章目录 文章目录 系列文章目录前言一、前提条件二、CANoe配置三、PicoScope接线四、CANoe捕捉报文五、眼图功能前言 本文档主要介绍如何使用CANoe Option .Scope捕获CAN总线上的物理波形,并利用眼图进行分析。 一、前提条件 使用CANoe Option .Scope,需要具备以下条件…

Folx软件下载及安装教程

简介: Folx Pro是一款适合Mac的专业下载工具也是一款BT下载器,Folx中文版有一个支持Retina显示的现代界面,提供独特的系统排序、存储下载内容与预览下载文件。Folx中文官网提供Folx教程、激活码、下载。 安 装 包 获 取 地 址: …

c->c++(一):部分KeyWord

本文主要探讨c相关关键字的使用。 char char默认是unsigned/signed取决平台,wchar_t宽字符:用于Unicode编码(超过一个字节),用wcin和wcout输入输出,字符串为wstring char8_t(20),char16_t(11起),char32_t(11):指定占用字节数且是无符号,字符串类u8string,u16s…

传闻Google谷歌代投印度slots游戏广告效果备受关注

传闻Google谷歌代投印度slots游戏广告效果备受关注 在印度,随着互联网的普及和移动设备的广泛使用,网络游戏和在线娱乐产业逐渐兴起。其中,“slots游戏”作为一种受欢迎的在线博彩形式,吸引了大量玩家。对于广告主而言&#xff0…

这世上又多了一只爬虫(spiderflow)

让我们一起默念: 爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫爬虫 接着大声喊出来: 一!只!爬!虫!呀!爬!呀!爬&#xf…

解析FTP服务器:从基础知识到vsftpd实战操作

✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…

惠海 H6213L降压恒压IC 支持3.3V5V12V30V40V60V100V电动车仪表供电稳压芯片方案

H6213L高压降压开关控制器是一款功性能良好的电源管理解决方案。它集成了众多先进的功能,使其在各种高压输入的应用场景中都能表现出色。 首先,H6213L具备高达150V的耐压能力,并支持高达120V的宽压输入范围。这意味着它可以轻松应对各种高压…

时间卷积网络与膨胀卷积:深入理解其原理与应用

TCN, Temporal Convolutional Networks 时间卷积网络与膨胀卷积:深入理解其原理与应用一、时间卷积网络(TCN)简介二、膨胀卷积的核心概念1. **膨胀卷积(Dilated Convolution)**2. **Kernel(卷积核&#xff…

Rejetto HTTP文件服务器 未授权RCE漏洞复现(CVE-2024-23692)

0x01 产品简介 Rejetto HTTP File Server(HFS)是一个基于HTTP协议的文件服务器软件,旨在为用户提供简单、轻量级且易于使用的文件共享解决方案。功能强大、易于使用的文件服务器软件,无论是个人使用还是团队协作,HFS都能满足用户的需求,提高工作效率。 0x02 漏洞概述 …

Zig标准库:最全数据结构深度解析(2)

1.1 queue structures LinearFifo:缓冲区是FIFO内部的一个组成部分,其大小按照指定的尺寸设定。初始化时,这个缓冲区是以切片的形式传递给初始化函数的。为了动态管理缓冲区,使用了一个名为mem.Allocator的内存分配器。 fifo.zi…

鸿蒙轻内核Kconfig使用笔记

鸿蒙轻内核使用Kconfig进行图形化配置,本文专门讲解下鸿蒙轻内核LiteOS-M和LiteOS-A的图形化配置方法。本文中所涉及的源码,均可以在开源站点 https://gitee.com/openharmony/kernel_liteos_a 、 https://gitee.com/openharmony/kernel_liteos_m 获取。本…

【NLP练习】Transformer中的位置编码

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 一、什么是位置编码 1. 位置编码定义 Transformer 模型中的位置编码是为了在处理序列数据时引入位置信息,以便模型能够分辨输入序列中不同位置的词…

Cask ‘oraclexxx‘ is unavailable: No Cask with this name exists.

brew search oracle-jdk或brew search --cask oracle-jdk 原因:Homebrew官方仓库不再维护多个旧版本的OracleJDK 不推荐使用Homebrew环境安装JDK //指定版本安装 brew install --cask temurin17 //设置 JAVA_HOME 环境变量 //找到安装的JDK 版本的路径 /usr/lib…

Pytorch环境配置的方法

Pytorch虚拟环境配置全流程 以安装pytorch1.9.1为例 1. 创建虚拟环境 安装Anaconda3,打开 PowerShell 创建虚拟环境并进入: conda create -n torch1.9.1 python3.8 conda activate torch1.9.1 conda create -n torch1.9.1 python3.8 conda activate to…

Day 22:2786. 访问数组中的位置使分数最大

Leetcode 2786. 访问数组中的位置使分数最大 给你一个下标从 0 开始的整数数组 nums 和一个正整数 x 。 你 一开始 在数组的位置 0 处&#xff0c;你可以按照下述规则访问数组中的其他位置&#xff1a; 如果你当前在位置 i &#xff0c;那么你可以移动到满足 i < j 的 任意 …

图解 React diff 算法

Render 阶段会生成 Fiber Tree&#xff0c;所谓的 diff 实际上就是发生在这个阶段&#xff0c;这里的 diff 指的是 current FiberNode 和 JSX 对象之间进行对比&#xff0c;然后生成新的的 wip FiberNode。 除了 React 以外&#xff0c;其他使用到了虚拟 DOM 的前端框架也会有类…

Springboot(若依)国际化配置接口访问后返回????????

最近使用若依的框架进行二次开发&#xff0c;配置了国际化&#xff0c;application.yml配置英文时没问题&#xff0c;但配置中文basename: i18n/messages_zh_CN&#xff0c;访问接口就直接返回的???&#xff0c;如图&#xff1a; 于是检查了I18nConfig文件&#xff0c;没配错…

【Linux】基础IO——文件描述符,重定向

话接上篇&#xff1a; 1.文件描述符fd 磁盘文件 VS 内存文件&#xff1f; 当文件存储在磁盘当中时&#xff0c;我们将其称之为磁盘文件&#xff0c;而当磁盘文件被加载到内存当中后&#xff0c;我们将加载到内存当中的文件称之为内存文件。磁盘文件和内存文件之间的关系就像程…

数据结构:手撕代码——顺序表

目录 1.线性表 2.顺序表 2.1顺序表的概念 2.2动态顺序表实现 2.2-1 动态顺序表实现思路 2.2-2 动态顺序表的初始化 2.2-3动态顺序表的插入 检查空间 尾插 头插 中间插入 2.2-4 动态顺序表的删除 尾删 头删 中间删除 2.2. 5 动态顺序表查找与打印、销毁 查找 …