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

发布于:2024-06-22 ⋅ 阅读:(75) ⋅ 点赞:(0)

解析服务器端代码

代码是放在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());
                }
            }
        };


网站公告

今日签到

点亮在社区的每一天
去签到