坦克大战--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++] = '\0'; // @分隔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++] = '\0'; // 空格分隔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类型 ---- (3)实现socket通信的更多相关文章
- 坦克大战--Java类型
		
写在前面 Java编译器下载教程(真的良心):https://blog.csdn.net/Haidaiya/article/details/81230636 本项目为本人独自制作,请各位尊 ...
 - 坦克大战--Java类型 ---- (2)按键设置和用户名的输入
		
一.实现思路(emmmm,这个地方我很大程度参照了别人的写法) 由于键盘按键众多,因此使用选择框JComboBox 进行按键选择,点击一个JButton 按钮后,读取所有选择框中的内容,然后存到一 ...
 - 坦克大战--Java类型 ---- (1)音乐播放
		
实现原理 我用接口java.applet.AudioClip实现音乐播放,那么我们需要了解这个接口的情况. 我们主要使用其中的三个方法: (1)void loop(); //循环播放(2)void p ...
 - Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制
		
Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制 JAVA 中原生的 socket 通信机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.co ...
 - 我看不下去鸟。。。。Java和C#的socket通信真的简单吗?
		
这几天在博客园上看到好几个写Java和C#的socket通信的帖子.但是都为指出其中关键点. C# socket通信组件有很多,在vs 使用nuget搜索socket组件有很多类似的.本人使用的是自己 ...
 - java和C#之间SOCKET通信的问题
		
转自:http://www.cdtarena.com/javapx/201307/9170.html java和C#之间SOCKET通信的问题 一.服务器端(使用java编写) /** * 监听客户端 ...
 - Java和C#的socket通信相关(转)
		
这几天在博客园上看到好几个写Java和C#的socket通信的帖子.但是都为指出其中关键点. C# socket通信组件有很多,在vs 使用nuget搜索socket组件有很多类似的.本人使用的是自己 ...
 - Java进阶(四十七)Socket通信
		
Java进阶(四十七)Socket通信 今天讲解一个 Hello Word 级别的 Java Socket 通信的例子.具体通讯过程如下: 先启动Server端,进入一个死循环以便一直监听某端口是 ...
 - Java实现简单的socket通信
		
今天学习了一下java如何实现socket通信,感觉难点反而是在io上,因为java对socket封装已经很完善了. 今天代码花了整个晚上调试,主要原因是io的flush问题和命令行下如何运行具有pa ...
 
随机推荐
- HTML5属性备忘单
			
在网上闲逛的时候看到了文章,感觉总结的这个html5文章,决定转载过来,在排版的时候也帮助自己重新梳理复习一遍.毕竟学习基础最重要. by zhangxinxu from http://www.zha ...
 - [笔记]共享内存(shm)
			
一.特点 共享内存允许多个不同的进程可以访问同一块内存.相较于其他IPC形式,具有速度快,效率高的特点,共享内存的存在降低了在大规模数据处理过程中内存的消耗. 二.创建共享内存 1.头文件 #incl ...
 - Vue_(组件通讯)使用solt分发内容
			
Vue特殊特性slot 传送门 有时候我们需要在自定义组件内书写一些内容,例如: <com-a> <h1>title</h1> </com-a> 如果想 ...
 - Android学习_Fragment
			
Fragment 使用Fragment 我们可以把屏幕划分成几块,然后进行分组,进行一个模块化的管理.从而可以更加方便的在运行过程中动态地更新Activity的用户界面.另外Fragment并不能单独 ...
 - 07.斐波那契数列 Java
			
题目描述 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0). n<=39 思路 递归 若n<=2;返回n; 否则,返回Fibonacci ...
 - JS基础_break跳出外层循环
			
可以为循环语句创建一个label,来表示当前循环 label:循环语句 使用break语句时,可以在break后跟着一个label 这样break会结束指定的循环 outer: for(let i=0 ...
 - koa 基础(二十四)封装 DB 库 --- 新增数据、更新数据、删除数据
			
1.根目录/module/db.js /** * DB库 */ var MongoClient = require('mongodb').MongoClient; var Config = requi ...
 - 【.net core 0基础】创建你的第一个.net core应用
			
1.下载.NET core相应的SDK,https://dotnet.microsoft.com/download 2.安装完成后,打开命令提示符,输入命令 dotnet,检查是否正确安装,如果命令能 ...
 - mysql 存储过程中使用动态sql语句
			
Mysql 5.0 以后,支持了动态sql语句,我们可以通过传递不同的参数得到我们想要的值 这里介绍两种在存储过程中的动态sql: set sql = (预处理的sql语句,可以是用concat拼接的 ...
 - Cortex-M3 操作模式与特权等级
			
Cortex-M3支持2个模式(Handler模式.线程模式)和2个特权等级(特权级.非特权级). 当处理器处在线程模式时,既可以使用特权级,也可以使用非特权级. 当处理器处在Handler模式时,总 ...