• 坦克大战--Java类型 ---- (3)实现socket通信


    一、实现思路

    使用socket通信的一些方法来实现socket通信,客户端和服务端两边需要约定好通信的接口Port(尽量选高的),客户端需要服务端的IP地址,以实现数据交流。

    同时,客户端和服务端需要约定好数据传输的方式,比如我这里用 '!' 作为传输数据结束的标志,用'@'实现不同类型数据的分隔。

    还有就是服务端那边需要保存排行榜的信息,由于那时候我还不会用数据库,所以用对象流将数据存入服务端的文件中,每次开启服务器就读取这个文件的信息。

    在我这个程序里面,客户端向服务端发送的有两种请求,上传数据(上传用户得分),下载数据(获取排行榜),所以需要在服务端判断用户的请求,并执行对应的操作。

    二、注意事项

    1)socket通信的时候要选好接口号Port,不能出现选择的接口号被其他服务占用。

    2)客户端中的Socket 对象,要输入服务端的IP地址和接口号Port,我的代码里面为了方便,把自己的电脑作为服务端,所以用InetAddress.getByName("localhost")来获取本地IP地址,以实现socket通信

    3)代码区给出的代码里面的ranking是排行榜信息,本博文没有给出

    三、socket通信的常用模板

    1)客户端向服务端发送数据

    //这里为了不想多次修改本机的IP地址,直接获取本机IP地址
    Socket socket = new Socket(InetAddress.getByName("localhost"), 7879);
    //输出流
    OutputStream os = socket.getOutputStream(); //设置每次传输的数据量 BufferedOutputStream bos = new BufferedOutputStream(os, 16); //获取排行榜的请求 String news = new String("downlLoad"); // 下载数据 //一般是用字节流进行传输 byte[] bb = news.getBytes(); // 发送数据包 bos.write(bb); bos.flush();

      2)客户端接收服务端信息

    //向服务端发送请求后,准备接受服务端出传入的信息
    InputStream is = socket.getInputStream();
    //设置每次传输的数据量
    BufferedInputStream bis = new BufferedInputStream(is, 16);
    byte[] b = new byte[16];
    //order记录获取的整个数据
    char[] order = new char[600];
    //表示order中的字符数,也可以当作字符串的长度
    int tot = 0;
    //获取服务端传入的信息
    while ((bis.read(b) != -1)) {
    //结束判断
        boolean end = false;
        for (int i = 0; i < 16; i++) {
            if ((char) b[i] == '!') {
               //约定号用 '!' 作为结束标记
                end = true;
                break;
              }
      //将服务端传入的信息转化为字符
       order[tot++] = (char) b[i];
    }
    if (end) {
      break;
    }
    //这个不能少,重置获取信息的字节数组
     b = new byte[16];
    }
    //关闭客户端
    socket.close();

      3)服务端接收客户端信息

    try {
                //服务端和客户端双方约定好接口号
                ServerSocket serverSocket = new ServerSocket(7879);
                Socket socket = null;
                socket = serverSocket.accept();
                InputStream is = socket.getInputStream();
                BufferedInputStream bis = new BufferedInputStream(is, 16);
                byte[] b = new byte[16];
                //order代表客户端传入的请求
                char[] order = new char[16];
                while ((bis.read(b)) != -1) {
                     boolean end = false;
                     for (int i = 0; i < 16; i++) {
                         order[i] = (char) b[i];
                         if(order[i] == '!') {
                             //约定好用'!'作为传输结束标志
                             end = false;
                             break;
                         }
                     }
                     if(end) {
                         break;
                     }
               }
         } catch (IOException e) {
             e.printStackTrace();
         }

      4)服务端向客户端发送信息

                     OutputStream os = socket.getOutputStream();
                     BufferedOutputStream bos = new BufferedOutputStream(os, 16);
                     byte[] bb = ranking.toString().getBytes();
                     byte[] ends = new String("!").getBytes(); // 输入结束命令
                     bos.write(bb);// 发送数据包
                     bos.flush();
                     bos.write(ends);
                     bos.flush();

    四、代码区

      类Cilent

    package component;
    
    import java.io.*;
    import java.net.*;
    
    public class Client {
    
        public static void main(String[] args) {
            new Client(null);
        }
    
        public Client(GameOver gameover) {
            
        }
        
        //数据下载,从服务端获取排行榜信息
        public boolean downLoad(String name , Key key) {
            try {
                //这里为了不想多次修改本机的IP地址,直接获取本机IP地址
                Socket socket = new Socket(InetAddress.getByName("localhost"), 7879);
                //输出流
                OutputStream os = socket.getOutputStream();
                //设置每次传输的数据量
                BufferedOutputStream bos = new BufferedOutputStream(os, 16);
                //获取排行榜的请求
                String news = new String("downlLoad"); // 下载数据
                //一般是用字节流进行传输
                byte[] bb = news.getBytes();
                // 发送数据包
                bos.write(bb);
                bos.flush();
    
                //向服务端发送请求后,准备接受服务端出传入的信息
                InputStream is = socket.getInputStream();
                //设置每次传输的数据量
                BufferedInputStream bis = new BufferedInputStream(is, 16);
                byte[] b = new byte[16];
                //order记录获取的整个数据
                char[] order = new char[600];
                //表示order中的字符数,也可以当作字符串的长度
                int tot = 0;
    
                //获取服务端传入的信息
                while ((bis.read(b) != -1)) {
                    //结束判断
                    boolean end = false;
                    for (int i = 0; i < 16; i++) {
                        if ((char) b[i] == '!') {
                            //约定号用 '!' 作为结束标记
                            end = true;
                            break;
                        }
                        //将服务端传入的信息转化为字符
                        order[tot++] = (char) b[i];
                    }
                    if (end) {
                        break;
                    }
                    //这个不能少,重置获取信息的字节数组
                    b = new byte[16];
                }
                //关闭客户端
                socket.close();
                //将从服务器获取的排行榜信息组成排行榜
                return new RankingList(name,key).print(new String(order));
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return false;
            
            
        }
    
        public boolean upData(char mode, String name, String score) {
            try {
                //本地服务端
                Socket socket = new Socket(InetAddress.getByName("localhost"), 7879);
                OutputStream os = socket.getOutputStream();
                BufferedOutputStream bos = new BufferedOutputStream(os, 16);
                //客户端和服务端约定好数据处理方式,以便互相“理解”
                String news = new String("upLoad" + mode + "@" + name + "@" + score + "@");
                byte[] bb  = news.getBytes();
                
                bos.write(bb);// 发送数据包
                bos.flush();
                //关闭客户端
                socket.close();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return false;
        }
    }

      类Sever

    package component;
    
    import java.io.*;
    import java.net.*;
    
    public class Server {
        //保存排行榜信息
        private Ranking ranking = null;
    
        public static void main(String args[]) {
            new Server();
        }
    
        public Server() {
            //先在服务端本地读取排行榜的数据,用对象流
            ObjectInputStream rank_in = null;
            try {
                File file = new File("ranking.txt");
                // 文件不存在,则开一个新的
                if (!file.exists()) {
                    file.createNewFile();
                    ranking = new Ranking();
                } else {
                    // 文件存在,直接读取
                    rank_in = new ObjectInputStream(new FileInputStream(file));
                    ranking = (Ranking) rank_in.readObject();
                }
            } catch (FileNotFoundException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } catch (ClassNotFoundException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } finally {
                if (rank_in != null) {
                    try {
                        rank_in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            //及时保存
            this.save();
    
            try {
                //服务端和客户端双方约定好接口号
                ServerSocket serverSocket = new ServerSocket(7879);
                Socket socket = null;
                while (true) {
                    socket = serverSocket.accept();
                    InputStream is = socket.getInputStream();
                    BufferedInputStream bis = new BufferedInputStream(is, 16);
                    byte[] b = new byte[16];
                    //order代表客户端传入的请求
                    char[] order = new char[16];
    
                    while ((bis.read(b)) != -1) {
                        boolean end = false;
                        for (int i = 0; i < 16; i++) {
                            order[i] = (char) b[i];
                            if(order[i] == '!') {
                                //约定好用'!'作为传输结束标志
                                end = false;
                                break;
                            }
                        }
                        if(end) {
                            break;
                        }
                        //第一种请求,上传用户数据
                        if (order[0] == 'u' && order[1] == 'p' && order[2] == 'L' && order[3] == 'o' && order[4] == 'a'
                                && order[5] == 'd') {
                            //分别代表关卡,用户名,分数
                            char section = order[6];
                            String name = null;
                            String score = null;
    
                            //代表客户端传入的信息
                            char[] in = new char[50];
                            //字符串长度
                            int index = 0;
                            //index当前代表的是什么,(关卡,用户名,分数)
                            int mode = 1;
                            //System.out.println("first");
                            //这里是处理上一次数据剩余的数据
                            for (int i = 8; i < 16; i++) {
                                if (order[i] != '@') {
                                    //@是数据类型分隔符
                                    in[index++] = order[i];
                                } else {
                                    in[index++] = ''; // @分隔name和score
                                    if (mode == 1) {
                                        mode++;
                                        name = new String(in); // 第一次为姓名
                                    } else {
                                        score = new String(in);//第二次为分数
                                        mode++;
                                        break;
                                    }
                                    in = new char[50];
                                    index = 0;
                                }
                            }
                            //System.out.println("second");
                            order = new char[16]; // 为读入下一组
                            //这里是继续读取
                            while ((bis.read(b)) != -1 && mode < 3) {
    
                                for (int i = 0; i < 16; i++)
                                    order[i] = (char) b[i];
                                System.out.println(order);
                                for (int i = 0; i < 16; i++) {
                                    if (order[i] != '@') {
                                        in[index++] = order[i];
                                    } else {
                                        System.out.println(mode);
                                        in[index++] = ''; // 空格分隔name和score
                                        if (mode == 1) {
                                            mode++;
                                            name = new String(in); // 第一次为姓名
                                        } else {
                                            mode++;
                                            score = new String(in);//第二次为分数
                                            break;
                                        }
                                        in = new char[50];
                                        index = 0;
                                    }
                                }
                                //数据读取完毕,退出
                                if(mode == 3) {
                                    break;
                                }
                            }
                            //System.out.println("third: "+mode);
                            //System.out.println("third");
                            ranking.add(section, name, score);//向Ranking对象添加新的数据,具体判断在ranking里面
                            //System.out.println(ranking.toString());
                            this.save();
                            //System.out.println("end");
                        } else {
                            //第二种请求,获取排行榜
                            //System.out.println("download");
                            OutputStream os = socket.getOutputStream();
                            BufferedOutputStream bos = new BufferedOutputStream(os, 16);
                            byte[] bb = ranking.toString().getBytes();
                            byte[] ends = new String("!").getBytes(); // 输入结束命令
                            bos.write(bb);// 发送数据包
                            bos.flush();
                            bos.write(ends);
                            bos.flush();
                        }
                        break;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public void save() {
            ObjectOutputStream rank_out = null;
            try {
                // 为保证及时性,先删除文件然后再创建新的
                File file = new File("ranking.txt");
                file.delete();
                file.createNewFile();
                rank_out = new ObjectOutputStream(new FileOutputStream("ranking.txt"));
                rank_out.writeObject(ranking);
                System.out.println(ranking);
                rank_out.flush();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (rank_out != null) {
                    try {
                        rank_out.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    
    }
  • 相关阅读:
    (转)分布式系统原理
    Java常用排序
    19.Java5同步集合类的应用
    18.Java5阻塞队列的应用
    17.Java5的Exchanger同步工具
    16.Java5的CountDownLatch同步工具
    15.Java5的CyclicBarrier同步工具
    14.Java5的Semaphere同步工具
    13.Java5条件阻塞Condition的应用
    Docker部署JavaWeb项目实战
  • 原文地址:https://www.cnblogs.com/winter-bamboo/p/10838797.html
Copyright © 2020-2023  润新知