参考:https://blog.csdn.net/qq_43842093/article/details/129964892
https://blog.csdn.net/weixin_42408447/article/details/126437276
数据类型占用字节数:
https://blog.csdn.net/weixin_42408447/article/details/126437276
数据类型占用字节数:
// Java一共有8种基本数据类型: // 1、int占4字节,取值范围为“-2147483648~2147483647”; // 2、short占2字节,取值范围为“-32768~32767”; // 3、long占8字节; // 4、byte占1字节,取值范围为“-128~127”; // 5、float是单浮点类型,占4字节; // 6、double是双浮点类型,占8字节; // 7、char占2字节; // 8、boolean占1字节。
服务端:
import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @author jay * @create 2023-04-12 14:59 * 多线程下socket,服务端 */ public class ServerSocketTest2 { public static void ServerStart() { try { // 初始化服务端socket并且绑定9999端口 ServerSocket serverSocket = new ServerSocket(9999); // 创建一个线程池,开100个线程等待客户端连接。 ExecutorService executorService = Executors.newFixedThreadPool(100); while (true) { // 监听socket创建的连接并接受到它,此为阻塞方法,直到连接创建。 // 不能放到Runnable中,得到连接后才启用新线程,不然会立刻把线程池占满,一直在循环产生新线程。 Socket socketClient = serverSocket.accept(); Runnable runnable = () -> { // 通过包类型+包长度+消息内容定义一个socket通信对象。 // 数据类型为byte类型,包长度为int类型,消息内容为byte类型。 try { // 获取socket客户端输入流 InputStream inputStream = socketClient.getInputStream(); DataInputStream dataInputStream = new DataInputStream(inputStream); // server端输出流,输出数据给客户端。 OutputStream outputStream = socketClient.getOutputStream(); DataOutputStream dataOutputStream = new DataOutputStream(outputStream); // 连接状态,客户端执行socket.shutdownOutput();后连接会被关闭。 while (socketClient.isConnected()) { // 读取数据类型标识 byte b = dataInputStream.readByte(); // 读取数据总长度 int lenAccept = dataInputStream.readInt(); // 读取数据内容,此处要移除5个长度,是和客户端发送的内容约定好的。 byte[] dataAccept = new byte[lenAccept - 5]; dataInputStream.readFully(dataAccept); // 把读取到的数据转为String String strAccept = new String(dataAccept); System.out.println("Server获取的数据类型为:" + b); System.out.println("Server获取的数据长度为:" + lenAccept); System.out.println("Server获取的数据内容为:" + strAccept); // 写入,输出给客户端。 String strOut = "Server已接收到数据!"; int typeOut = 1; byte[] dataOut = strOut.getBytes(); int lenOut = dataOut.length + 5; dataOutputStream.writeByte(typeOut);// writeByte 长度1字节 dataOutputStream.writeInt(lenOut);// writeInt 长度4字节 dataOutputStream.write(dataOut);// write 长度为data[]的length长度 dataOutputStream.flush();// 提交输出数据 break; } } catch (IOException e) { e.printStackTrace(); } }; executorService.submit(runnable); } } catch (Exception e) { e.printStackTrace(); } } }
客户端:
import java.io.*; import java.net.Socket; /** * @author jay * @create 2023-04-12 15:05 * https://blog.csdn.net/weixin_42408447/article/details/126437276 */ public class ClientSocket2 { public static void ClientStart() { try { Socket socket = new Socket("127.0.0.1", 9999); // 客户端输出流,输出数据给服务端。 OutputStream outputStream = socket.getOutputStream(); DataOutputStream dataOutputStream = new DataOutputStream(outputStream); // 客户端输入流,获取服务端返回的数据。 InputStream inputStream = socket.getInputStream(); DataInputStream dataInputStream = new DataInputStream(inputStream); String str = "Client发送的数据!"; int type = 1; byte[] data = str.getBytes(); int len = data.length + 5; // len = len + type + data 的长度。 // 客户端按顺序write,服务端同样按顺序读取。 dataOutputStream.writeByte(type);// writeByte 长度1字节 dataOutputStream.writeInt(len);// writeInt 长度4字节 dataOutputStream.write(data);// write 长度为data[]的length长度 //刷新输出流,把write提交进去,不然服务端没接收到内容。 dataOutputStream.flush(); // 接收Server端返回的数据 // 读取数据类型标识 byte b = dataInputStream.readByte(); // 读取数据总长度 int lenAccept = dataInputStream.readInt(); // 读取数据内容,此处要移除5个长度,是和客户端发送的内容约定好的。 byte[] dataAccept = new byte[lenAccept - 5]; dataInputStream.readFully(dataAccept); // 把读取到的数据转为String String strAccept = new String(dataAccept); System.out.println("Client接收到返回数据:" + strAccept); // 关闭和释放资源 socket.shutdownOutput(); } catch (IOException e) { e.printStackTrace(); } } }
调用
Thread th1 = new Thread(new Runnable() { @Override public void run() { ServerSocketTest2.ServerStart(); } }); th1.start(); new Thread(new Runnable() { @Override public void run() { ClientSocket2.ClientStart(); } }).start();
调用socket.close()或者socket.shutdownOutput()方法,通知服务端数据输出已经完成。
调用这两个方法,都会结束客户端socket,但是有本质的区别。
socket.close() 将socket关闭连接,那边如果有服务端给客户端反馈信息,此时客户端是收不到的。
而socket.shutdownOutput()是将输出流关闭,此时,如果服务端有信息返回,则客户端是可以正常接收的。