前言:经过前三次的学习,今天又深入了一步。组长说,你尝试下传byte数组,你会遇到坑的。前几次,为了方便,我读流和写流都是用的readUTF()和writeUTF().直接写的String类型。于是我尝试了一下,直接传byte数组。代码如下:
Server端:
package mysocket.versiontwo;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* Created by demi on 16/10/12.
*/
public class JsonServer {
public static void main(String args[]) {
ServerSocket ss = null;
Socket s = null;
Thread thread = null;
try {
ss = new ServerSocket(3320);
while (true) {
s = ss.accept();
System.out.println("Client :" + s.getInetAddress() + " : " + s.getPort() + " 已连接》》》》》》");
thread = new Thread(new ServerThread(s));
thread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
ServerThread.java
package mysocket.versiontwo;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
/**
* Created by demi on 16/10/14.
*/
public class ServerThread implements Runnable {
private Socket s = null;
DataInputStream dis = null;
DataOutputStream dos = null;
public ServerThread(Socket s) {
this.s = s;
}
@Override
public void run() {
try {
dos = new DataOutputStream(s.getOutputStream());
dis = new DataInputStream(s.getInputStream());
while (true) {
byte[] bytes = new byte[1024];
dis.read(bytes);
String data= new String( bytes ,"UTF-8");
System.out.println(new String( bytes ,"UTF-8"));
if (null != data) {
if (!data.contains("data")) {
JSONObject jo = new JSONObject(data);
int a = jo.getInt("numA");
int b = jo.getInt("numB");
dos.write(creatSumJson(a, b).getBytes("UTF-8"));//写入数据到客户端
dos.flush();
} else {
JSONObject jo = new JSONObject(data);
int a = jo.getInt("data");
for (int i = 0; i < 100; i++) {
a++;
dos.write(createRandomJson(a).getBytes("UTF-8"));//写入数据到客户端
dos.flush();
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
try {
dis.close();
dos.close();
s.close();
System.out.print("链接已断开");
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
/**
* 模拟现实项目中的接口,在做了自加运算后创建一个json。
*/
public static String createRandomJson(int a) {
JSONObject s = new JSONObject();
try {
s.put("data", a);
} catch (JSONException e) {
e.printStackTrace();
}
return s.toString();
}
/**
* 模拟现实项目中的接口,获取客户端的两个加数,做完加法后返回给客户端。
*/
//
public static String creatSumJson(int a, int b) {
JSONObject s = new JSONObject();
try {
s.put("sum", a + b);
} catch (JSONException e) {
e.printStackTrace();
}
return s.toString();
}
}
Client端:
package mysocket.versiontwo;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Random;
/**
* Created by demi on 16/10/12.
*/
public class JsonClient {
public static void main(String args[]){
DataOutputStream dos =null;
Thread chat = null;
Socket socket = null;
DataInputStream dis =null;
try {
socket =new Socket("127.0.0.1",3320);
dos =new DataOutputStream(socket.getOutputStream());
dos.write(createRandomJson().getBytes("UTF-8")); //写入数据到服务器端
chat = new Thread(new ChatThread(socket));
chat.start();
socket.setKeepAlive(true);
int i = 0;
while(i<=100){
Thread.sleep(1000);
dos.write(creatSumJson().getBytes("UTF-8"));//写入数据到服务器端
i++;
}
} catch (IOException e) {
e.printStackTrace();
try {
dos.close();
socket.close();
chat.stop();
System.out.print("链接已断开");
} catch (IOException e1) {
e1.printStackTrace();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 模拟现实项目中的接口,创建一个20以内的随机数的json,发送到服务器,让服务器做++运算,加一次向客户端推送一次结果。
*/
public static String createRandomJson(){
JSONObject s = new JSONObject();
try {
s.put("data", new Random().nextInt(20));
} catch (JSONException e) {
e.printStackTrace();
}
return s.toString() ;
}
/**
* 模拟现实项目中的接口,创建两个100以内的随机数的json,发送到服务器,让服务器做完加法后返回给客户端。
*/
//
public static String creatSumJson(){
JSONObject s =new JSONObject();
try {
s.put("numA", new Random().nextInt(100));
s.put("numB", new Random().nextInt(100));
} catch (JSONException e) {
e.printStackTrace();
}
return s.toString() ;
}
}
ChatThread.Java
package mysocket.versiontwo;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
/**
* Created by demi on 16/10/13.
*/
public class ChatThread implements Runnable {
private Socket s = null;
DataInputStream dis =null;
public ChatThread(Socket s){
this.s = s;
}
@Override
public void run() {
try {
dis =new DataInputStream(s.getInputStream());
while(true){
byte[] bytes = new byte[1024];
dis.read(bytes);
System.out.println(new String( bytes ,"UTF-8")); //打印来自服务器的数据
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
正高高兴兴的run并和组长说,没坑啊。结果程序一运行起来,坑就来了!请看截图
我发现客户端读数据的时候,读的长度是不确定的,有时候一次性读的多,有时候就读一个。所以这就需要一个分隔机制,来限制读的长度。那首先想到的就是,在读流之前告诉对方,我的流的byte数组的长度。这样就可以避免这个问题了。还有一个问题就是,之前我还能通过json字段来判断是哪个接口,现在咋判断呢?这就需要cmd(命令号了)。那就在传json前,先把cmd,byte数组的长度传过去,再传json。但听前辈们说还谣传一个标识符,来标记是哪一次请求,防止多次请求过后,返回回来的结果对应不上。这个值传到服务器,服务器也会把这个值再传回来,客户端判断这个值与传过去的值是否一致。来对应请求。修改后的代码如下:
ServerThread.java
package mysocket.versionfour;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
/**
* Created by demi on 16/10/14.
*/
public class ServerThread extends Thread {
private Socket s = null;
DataInputStream dis = null;
DataOutputStream dos = null;
public ServerThread(Socket s) {
this.s = s;
}
@Override
public void run() {
try {
dos = new DataOutputStream(s.getOutputStream());
dis = new DataInputStream(s.getInputStream());
while (true) {
readFromClient();
}
} catch (Exception e) {
e.printStackTrace();
try {
dis.close();
dos.close();
s.close();
System.out.print("链接已断开");
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
/**
* 模拟现实项目中的接口,在做了自加运算后创建一个json。
*/
public static String createRandomJson(int a) {
JSONObject s = new JSONObject();
try {
s.put("data", a);
} catch (JSONException e) {
e.printStackTrace();
}
return s.toString();
}
/**
* 模拟现实项目中的接口,获取客户端的两个加数,做完加法后返回给客户端。
*/
//
public static String creatSumJson(int a, int b) {
JSONObject s = new JSONObject();
try {
s.put("sum", a + b);
} catch (JSONException e) {
e.printStackTrace();
}
return s.toString();
}
public void write2Client(byte[] bytes,int tag) throws Exception{
dos.writeInt(bytes.length);//传过去的byte数组的长度
dos.writeInt(tag);
dos.write(bytes);
dos.flush();
}
public void readFromClient(){
try {
int length=dis.readInt();
byte[] bytes = new byte[length];
int cmd = dis.readInt();
int tag = dis.readInt();
dis.read(bytes,0,length);
String data= new String( bytes ,"UTF-8");
System.out.println(tag + ":" +new String( bytes ,"UTF-8"));
JSONObject jo = new JSONObject(data);
switch (cmd){
case CMD.SUM :
int a = jo.getInt("numA");
int b = jo.getInt("numB");
write2Client(creatSumJson(a, b).getBytes("UTF-8"),tag);
break;
case CMD.RANDOMADD :
int random = jo.getInt("data");
for (int i = 0; i < 100; i++) {
random++;
write2Client(createRandomJson(random).getBytes("UTF-8"),tag);
}
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
ClientReadTHread.java
package mysocket.versionfour;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
/**
* Created by demi on 16/10/13.
*/
public class ClientReadThread extends Thread {
private Socket s = null;
DataInputStream dis =null;
public ClientReadThread(Socket s){
this.s = s;
}
@Override
public void run() {
try {
dis =new DataInputStream(s.getInputStream());
while(true){
readFromServer();
}
} catch (Exception e) {
e.printStackTrace();
try {
dis.close();
s.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public void readFromServer() throws Exception{
int length=dis.readInt();
byte[] bytes = new byte[length];
int tag =dis.readInt();
dis.read(bytes,0,length);
System.out.println(tag+":"+new String( bytes ,"UTF-8")); //打印来自服务器的数据
}
}
ClientWriteThread.java
package mysocket.versionfour;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Random;
/**
* Created by demi on 16/10/13.
*/
public class ClientWriteThread extends Thread {
private static int tag;
private Socket s = null;
DataOutputStream dos =null;
public ClientWriteThread(Socket s){
this.s = s;
}
@Override
public void run() {
try {
dos = new DataOutputStream(s.getOutputStream());
byte[] bytes = createRandomJson().getBytes("UTF-8");
write2Server( bytes, CMD.RANDOMADD);
int i = 0;
while (i <= 100) {
Thread.sleep(1000);
byte[] sumBytes = creatSumJson().getBytes("UTF-8");
write2Server( sumBytes, CMD.SUM);
i++;
}
} catch (Exception e) {
e.printStackTrace();
try {
dos.close();
s.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
/**
* 模拟现实项目中的接口,创建一个20以内的随机数的json,发送到服务器,让服务器做++运算,加一次向客户端推送一次结果。
*/
public static String createRandomJson() {
JSONObject s = new JSONObject();
try {
s.put("data", new Random().nextInt(20));
tag = new Random().nextInt(1000)+1000;
} catch (JSONException e) {
e.printStackTrace();
}
return s.toString();
}
/**
* 模拟现实项目中的接口,创建两个100以内的随机数的json,发送到服务器,让服务器做完加法后返回给客户端。
*/
public static String creatSumJson() {
JSONObject s = new JSONObject();
try {
s.put("numA", new Random().nextInt(100));
s.put("numB", new Random().nextInt(100));
tag = new Random().nextInt(1000)+1000;
} catch (JSONException e) {
e.printStackTrace();
}
return s.toString();
}
public void write2Server( byte[] bytes, int cmd) throws Exception {
dos.writeInt(bytes.length);//传过去的byte数组的长度
dos.writeInt(cmd);//命令号,通过命令号来辨别是哪个接口!
dos.writeInt(tag);//标志位,标记是那哪一次请求。
dos.write(bytes);
//dos.writeUTF(createRandomJson());
dos.flush();
}
}
CMD.java
package mysocket.versionfour;
/**
* Created by demi on 16/10/14.
*/
public class CMD {
//两加数求和
public static final int SUM = 1001;
//随机数自加一
public static final int RANDOMADD = 1002;
}
运行结果就正常了。
这就是进步!下一步就开始封装Socket了!期待吧!