Java Socket 通信 (四)
来源:互联网 发布:淘宝手机版详情页尺寸 编辑:程序博客网 时间:2024/05/21 06:39
前言:经过前三次的学习,今天又深入了一步。组长说,你尝试下传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了!期待吧!
1 0
- Java Socket 通信 (四)
- 步步测试完善Java中Socket通信图解法(四) .
- Java(socket通信)
- Java Socket(四)编程实现基于 TCP 的 Socket 通信
- Android中的socket通信(四)
- C++ SOCKET通信模型(四)IOCP
- Java Socket应用(一)--Socket通信
- Java--Socket通信(单向)
- Java--Socket通信(双向)
- Java Socket通信(多线程)
- Java--Socket通信(双向)
- java Socket通信(二)
- Java(扩展Socket通信)
- Java Socket 通信 (一)
- Java Socket 通信 (二)
- Java Socket 通信 (三)
- Java Socket 通信 (五)
- Java--Socket通信(双向)
- Java IO流之规律总结
- javascript移动端手机事件,禁止页面滑动
- Linux kill, killall, kill -9
- 服务器同时启动两个tomcat
- Primes on Interval(素数打表+二分)
- Java Socket 通信 (四)
- 洛谷 P1034 矩形覆盖
- pcb 阻抗匹配
- Oracle 与Mysql区别
- Android开发体系--Activity和Fragment的生命周期
- 如何设置CentOS为中文显示
- 正则表达式学习笔记
- RunLoop已入门?不来应用一下?
- 常用命令