坦克大战--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();
                }
            }
        }
    }

}
原文地址:https://www.cnblogs.com/winter-bamboo/p/10838797.html