1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 【Java 网络编程】TCP 数据传输示例 ( 客户端参数设置 | 服务器端参数设置 |

【Java 网络编程】TCP 数据传输示例 ( 客户端参数设置 | 服务器端参数设置 |

时间:2024-05-23 19:01:05

相关推荐

【Java 网络编程】TCP 数据传输示例 ( 客户端参数设置 | 服务器端参数设置 |

文章目录

I 客户端代码示例II 服务器端代码示例III 运行结果

I 客户端代码示例

import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import .Inet4Address;import .InetSocketAddress;import .Socket;import java.nio.ByteBuffer;/*** TCP 客户端*/public class Client {public static void main(String[] args) {try {//I. 创建 Socket 对象并绑定本地端口//1. 创建空的 Socket 对象 , 方便之后设置参数Socket socket = new Socket();//2. 绑定本地端口socket.bind(new InetSocketAddress(Inet4Address.getLocalHost(), 8887));System.out.println("客户端 Socket 创建完毕");//II. 设置 Socket 对象参数 , 注意这些参数只能在客户端没有连接服务器的时候设置 , 连接服务器之后设置是无效的//1. 设置从 Socket 对象输入流中读取数据的阻塞等待超时时间//当与 Socket 对象关联的 InputStream 输入流执行 read() 操作时 , 其阻塞时间为这个超时时间//如果超过了该时间还没有收到任何数据 , 就会抛出异常socket.setSoTimeout(3000);//2. 设置是否可以复用 Socket 绑定的地址和端口号//Socket 连接在建立时 , 会使用之前绑定本地的 IP 地址和端口号//这个端口号在使用之后 , 2 分钟之内不允许再次使用//进行了该设置之后 , 可以在连接关闭之后 , 马上使用该本地 IP 地址和端口号socket.setReuseAddress(true);//3. 设置是否开启 Nagle 算法 , Nagle 算法会导致多次发送的少量数据合并 , 即沾包情况出现//在需要低延迟传输的情况下是需要关闭该算法的 , 该算法会导致数据沾包情况出现socket.setTcpNoDelay(true);//4. 在长时间 ( 2 小时 ) 没有数据交互 , 是否需要发送心跳包确认连接socket.setKeepAlive(true);//5. 调用 Socket 对象的 close 方法之后的处理方式// 1> 默认情况 : false , 0//如果 boolean on 设置成false , 不处理连接的缓存数据 , 调用 close 会立刻关闭连接//系统底层会操作输出流发送剩余缓存数据 , 将缓冲区中的数据发送给连接对方//如果设置 false 不会产生阻塞操作// 2> setSoLinger( true , 20 ) 情况 ://如果设置 boolean on 参数为 true , int linger 参数设置一个大于等于 0 的参数//那么在关闭的时候 , 阻塞 linger 毫秒 , 之后缓冲区如果还有数据 , 就会被丢弃//直接向连接对方发送结束命令 , 无需经过超时等待// 3> setSoLinger( true , 0 ) 情况 ://如果设置成 0 , 那么其后果是不阻塞 , 也不让系统接管输出流//立刻丢弃缓冲区数据 , 向对方发送 RST 命令socket.setSoLinger(true, 10);//6. 设置紧急数据是否内敛 , 默认情况时 false 关闭的//紧急数据 : 紧急数据是 Socket 对象通过调用 sendUrgentData 发送出去的数据//该方法参数是一个 int 值 , 仅有最低的 8 位是有效的socket.setOOBInline(true);//7. 设置发送接收缓冲区大小socket.setReceiveBufferSize(64 * 1024 * 1024);socket.setSendBufferSize(64 * 1024 * 1024);//8. 设置性能参数 : ① 连接时长 , ② 最低延迟 , ③ 带宽//设置的值不是具体的参数 , 而是连接的性能权重 , 对哪个性能要求比较高 ;//上面的延迟和带宽的性能是互斥的 , 低延迟新能好 , 带宽性能就差socket.setPerformancePreferences(0, 2, 0);System.out.println("客户端 Socket 参数设置完毕");//III. 连接服务器//1. 连接到服务器端的 8888 端口 , 设置连接超时 3000 毫秒socket.connect(new InetSocketAddress(Inet4Address.getLocalHost(), 8888), 3000);System.out.println("客户端 Socket 连接服务器完毕");//IV. 数据发送与接收//1. 获取输出流和输入流OutputStream outputStream = socket.getOutputStream();InputStream inputStream = socket.getInputStream();//2. 使用 ByteBuffer 向 byte[] 数组中存储数据byte[] buffer = new byte[256];ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);//3. 向数组写入 byte 类型数据byteBuffer.put((byte) 0x01);//4. 向数组中写入 short 类型数据byteBuffer.putShort((short) 1);//5. 向数组中写入 int 类型数据byteBuffer.putInt(1);//6. 向数组中写入 char 类型数据byteBuffer.putChar('a');//7. 向数组中写入 boolean 类型数据//此处使用 byte 类型模拟 , true 为 1, false 为 0boolean bool = true;byteBuffer.put((byte) (bool ? 1 : 0));//8. 向数组中写入 long 类型数据byteBuffer.putLong((long)1);//9. 向数组中写入 float 类型数据byteBuffer.putFloat(3.14f);//10. 向数组中写入 double 类型数据byteBuffer.putDouble(3.14);//11. 向数组中写入 String 类型数据//先把 String 字符串转为 byte[] 数组, 在放入 byteBuffer 中byteBuffer.put("Hello World".getBytes());//12. 将 byte[] 数据发送到服务器端outputStream.write(buffer, 0, byteBuffer.position() + 1);System.out.println("客户端 Socket 将各种类型数据发送到了服务器端");//13. 接收服务器端反馈的数据int readLen = inputStream.read(buffer);System.out.println("客户端 Socket 接收到服务器端数据 " + readLen + " 字节");//V. 释放资源//1. 关闭输入输出流outputStream.close();inputStream.close();} catch (IOException e) {e.printStackTrace();}}}

II 服务器端代码示例

import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import .Inet4Address;import .InetSocketAddress;import .ServerSocket;import .Socket;import java.nio.ByteBuffer;/*** TCP 服务器端*/public class Server {public static void main(String[] args) {try {//I. 设置服务器套接字//1. 创建服务器端 , 注意创建一个空的服务器套接字 , 一遍后面设置更详细的参数ServerSocket serverSocket = new ServerSocket();System.out.println("服务器端端 ServerSocket 创建完毕");//2. 设置从 Socket 对象输入流中读取数据的阻塞等待超时时间//当与 Socket 对象关联的 InputStream 输入流执行 read() 操作时 , 其阻塞时间为这个超时时间//如果超过了该时间还没有收到任何数据 , 就会抛出异常serverSocket.setSoTimeout(30000);//3. 设置是否可以复用 Socket 绑定的地址和端口号//Socket 连接在建立时 , 会使用之前绑定本地的 IP 地址和端口号//这个端口号在使用之后 , 2 分钟之内不允许再次使用//进行了该设置之后 , 可以在连接关闭之后 , 马上使用该本地 IP 地址和端口号serverSocket.setReuseAddress(true);//4. 设置发送接收缓冲区大小serverSocket.setReceiveBufferSize(64 * 1024 * 1024);//5. 设置性能参数 : ① 连接时长 , ② 最低延迟 , ③ 带宽//设置的值不是具体的参数 , 而是连接的性能权重 , 对哪个性能要求比较高 ;//上面的延迟和带宽的性能是互斥的 , 低延迟新能好 , 带宽性能就差serverSocket.setPerformancePreferences(0, 2, 0);System.out.println("服务器端端 ServerSocket 设置完毕");//6. 绑定本地端口 , 只有绑定了本地端口 , 服务器端套接字才能正式工作//服务器端才算是正式创建完毕//上面的设置一定要在绑定接口之前设置完毕 , 之后在设置 serverSocket 是无效的serverSocket.bind(new InetSocketAddress(Inet4Address.getLocalHost(), 8888), 88);System.out.println("服务器端端 ServerSocket 绑定 8888 端口完毕");//II. 等待服务器端连接//1. 服务器端阻塞 , 等待客户端连接服务器端的 8888 端口号Socket clientSocket = serverSocket.accept();//2. 创建客户端异步处理线程 , 处理服务器端与该客户端之间的交互 , 创建之后直接启动线程即可ClientHandler clientHandler = new ClientHandler(clientSocket);clientHandler.start();} catch (IOException e) {e.printStackTrace();}}/*** 客户端异步处理线程* 每当有客户端连接服务器 , 就开启一个线程处理与该客户端之间的交互*/private static class ClientHandler extends Thread {/*** 客户端线程*/private Socket clientSocket;public ClientHandler(Socket clientSocket) {this.clientSocket = clientSocket;}@Overridepublic void run() {super.run();System.out.println("客户端 : " + clientSocket.getInetAddress() + " 连接到服务器端");try {//I. 获取数据交互的输入流 , 输出流 , 及缓冲区//1. 从客户端 Socket 中获取与客户端进行数据交互的输入输出流OutputStream outputStream = clientSocket.getOutputStream();InputStream inputStream = clientSocket.getInputStream();//2. 从客户端读取数据 , 并使用 ByteBuffer 读取其中各种类型的数据byte[] buffer = new byte[256];int readCount = inputStream.read(buffer);ByteBuffer byteBuffer = ByteBuffer.wrap(buffer, 0, readCount);//II. 按照顺序读取存放的数据//注意 : 要按照存放的顺序读取//1. 读取 byte 类型数据byte var_byte = byteBuffer.get();System.out.println("① byte 类型数据 : " + var_byte);//2. 读取 short 类型数据short var_short = byteBuffer.getShort();System.out.println("② short 类型数据 : " + var_short);//3. 读取 int 类型数据int var_int = byteBuffer.getInt();System.out.println("③ int 类型数据 : " + var_int);//4. 读取 char 类型数据char var_char = byteBuffer.getChar();System.out.println("④ char 类型数据 : " + var_char);//5. 读取 short 类型数据boolean var_boolean = byteBuffer.get() == 1;System.out.println("⑤ boolean 类型数据 : " + var_boolean);//6. 读取 long 类型数据long var_long = byteBuffer.getLong();System.out.println("⑥ long 类型数据 : " + var_long);//7. 读取 float 类型数据float var_float = byteBuffer.getFloat();System.out.println("⑦ float 类型数据 : " + var_float);//8. 读取 double 类型数据double var_double = byteBuffer.getDouble();System.out.println("⑧ double 类型数据 : " + var_double);//9. 读取 short 类型数据int start = byteBuffer.position();String var_string = new String(buffer, start, readCount - start - 1);System.out.println("⑨ String 类型数据 : " + var_string);//III. 将接收的数据再发送回去, 并关闭连接outputStream.write(buffer, 0, readCount);outputStream.close();inputStream.close();} catch (IOException e) {e.printStackTrace();} finally {// 连接关闭try {clientSocket.close();} catch (IOException e) {e.printStackTrace();} finally {System.out.println("客户端与服务器端交互完成");}}}}}

III 运行结果

1. 先运行服务器端 :

服务器端端 ServerSocket 创建完毕服务器端端 ServerSocket 设置完毕服务器端端 ServerSocket 绑定 8888 端口完毕

2. 在运行客户端 :

客户端 Socket 创建完毕客户端 Socket 参数设置完毕客户端 Socket 连接服务器完毕客户端 Socket 将各种类型数据发送到了服务器端客户端 Socket 接收到服务器端数据 42 字节

3. 最终查看服务器端打印 :

服务器端端 ServerSocket 创建完毕服务器端端 ServerSocket 设置完毕服务器端端 ServerSocket 绑定 8888 端口完毕客户端 : /192.168.87.2 连接到服务器端① byte 类型数据 : 1② short 类型数据 : 1③ int 类型数据 : 1④ char 类型数据 : a⑤ boolean 类型数据 : true⑥ long 类型数据 : 1⑦ float 类型数据 : 3.14⑧ double 类型数据 : 3.14⑨ String 类型数据 : Hello World客户端与服务器端交互完成

【Java 网络编程】TCP 数据传输示例 ( 客户端参数设置 | 服务器端参数设置 | ByteBuffer 存放读取数据类型 )

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。