Java 使用UDP、TCP进行网络通信
2023-09-11 14:14:35 时间
UDP
工具类
public class UDP { private static final int port = 9000; //要使用的端口号 /** * 发送消息 * @Param ip 对方的ip,String * @Param msg 要发送的消息,String类型 */ public static void send(String ip,String msg) throws IOException { //对方的ip,不能直接用String,需要转换一下 InetAddress ipAddr = InetAddress.getByName(ip); //socket,相当于码头 DatagramSocket socket = new DatagramSocket(); // packet,数据包,相当于集装箱 // 参数:byte[]、数据长度、对方ip(不能直接写String)、要使用的端口号 // 什么类型都可以传输,比如传文件,不局限于String,因为都要转换为字节数组 DatagramPacket packet = new DatagramPacket(msg.getBytes(), msg.length(),ipAddr,port); //通过socket发送packet socket.send(packet); System.out.println("send:"+msg); //关闭socket socket.close(); } /** *监听端口,接收消息 */ public static void receive() throws IOException { //socket,指定要监听的端口。发送、接收使用的端口要相同 DatagramSocket socket = new DatagramSocket(port); // packet,用一个byte[]来存储数据 // 第一个数值是字节数组的长度,第二个数值是要读取的字节数,把读取到的数据放到byte[]中 // 读取的字节数要小于等于byte[]的长度,不然放不下 DatagramPacket packet = new DatagramPacket(new byte[1024], 1024); //一直监听 while (true){ socket.receive(packet); //通过socket接收packet,用packet来封装接收到的数据,没接收到数据时会一直阻塞 byte[] data = packet.getData(); //获取packet中的数据(整个byte[]) int length = packet.getLength(); //获取数据的实际长度。packet中的byte[]不一定是装满的,需要获取实际的字节数 String msg = new String(data, 0, length); //byte[]、offset、length // msg = new String(data); //其实不获取实际长度也行 System.out.println("received:"+msg); //获取本机ip、发送方ip // InetAddress localAddress = socket.getLocalAddress(); //本机 // InetAddress address = packet.getAddress(); //发送方 // String ip = address.getHostAddress(); //String类型的ip // socket.close(); //关闭socket //一直监听,不关闭socket // 退出聊天时,比如退出桌面程序或web项目点击“结束聊天”、超过2分钟未互动,需要关闭socket } } }
UDP不区分客户端、服务端,2边使用的socket都是DatagramSocket,使用的packet都是DatagramPacket。发送、接收可以使用同一个socket。
发送消息
public class Send { public static void main(String[] args) throws IOException { UDP.send("127.0.0.1", "hello"); } }
接收消息
public class Receive { public static void main(String[] args) throws IOException { UDP.receive(); } }
先启动接收方,再启动发送方。
有一个问题:写了2个主类,分别启动,一般不这么干,使用多线程代替。
测试类
public class Test { public static void main(String[] args) throws IOException, InterruptedException { //开启一条线程,监听端口、接收消息 Thread receiveThread = new Thread(new Runnable() { @Override public void run() { try { UDP.receive(); } catch (IOException e) { e.printStackTrace(); } } }); receiveThread.start(); //怕接收线程暂时没分配到时间片,在发送消息之后才执行,没能接收到掐前面的消息,可以让发送消息的线程沉睡会儿 Thread.sleep(100); //也可以单独开启一条线程来发送消息 UDP.send("127.0.0.1","hello"); } }
UDP是不可靠的,不管对方ip存不存在、对方有没有启动监听,直接发出去,不管对方能不能接收到。
TCP
工具类
public class TCP { private static final int port = 9000; //要使用的端口号 /** * 发送消息 * @Param ip 对方的ip,String * @Param msg 要发送的消息,String类型 */ public static void send(String ip,String msg) throws IOException { //客户端的socket。直接使用String类型的对方的ip Socket socket = new Socket(ip, port); //向服务端发送数据 OutputStream os = socket.getOutputStream(); //输出流 os.write(msg.getBytes()); //byte[] System.out.println("send:"+msg); } /** *监听端口,接收消息 */ public static void receive() throws IOException { //服务端的socket,指定要监听的端口 ServerSocket serverSocket = new ServerSocket(port); //一直监听 while (true) { //接收客户端的请求,并创建一个与之对应的Socket来与该客户端通信 Socket socket = serverSocket.accept(); //接收客户端发送的数据 InputStream is = socket.getInputStream(); byte[] buff = new byte[1024]; int length = is.read(buff); //将数据读取到byte[]中,返回读取到的字节数 java.lang.String msg = new java.lang.String(buff, 0, length); //有很多个String类,不要导错了 System.out.println("received:" + msg); // 获取本机ip、发送方ip // InetAddress localAddress = socket.getLocalAddress(); //本机 // InetAddress inetAddress = socket.getInetAddress(); //发送方// String ipAddress = localAddress.getHostAddress(); //获取String类型的IP // socket.close(); } } }
TCP要区分客户端、服务端,客户端用Socket,服务端用ServerSocket,通过ServerSocket获取与客户端对应的socket,来与客户端通信。
客户端、服务端是相对的,发送数据的一方叫做客户端,接收消息的一方叫做服务端,一般都要客户端、服务端。
接收到对方消息后,可以调用send()传入对方ip与之通信,也可以写个重载的send(),传入与客户端对应的socket。
测试类
public class Test { public static void main(String[] args) throws IOException, InterruptedException { //开启一条线程,监听端口、接收消息 Thread receiveThread = new Thread(new Runnable() { @Override public void run() { try { TCP.receive(); } catch (IOException e) { e.printStackTrace(); } } }); receiveThread.start(); //怕接收线程暂时没分配到时间片,在发送消息之后才执行,没能接收到掐前面的消息,可以让发送消息的线程沉睡会儿 Thread.sleep(100); //也可以单独开启一条线程来发送消息 TCP.send("127.0.0.1","hello"); } }
TCP是可靠的,三次握手确定双方可以正常通信。
相关文章
- [Java基础] java的守护线程与非守护线程
- Java 开发环境配置--eclipse工具进行java开发
- JAVA 注解教程(四)Java 预置的注解
- Java实现 LeetCode 234 回文链表
- Java实现 蓝桥杯 算法训练 字串统计
- Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
- Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
- 【java】基于Tomcat的WebSocket转帖 + 自己理解
- 【JAVA】Java循环语句中的continue跳转进入下一次循环是否判断循环条件
- Eclipse 报 “Exception in thread "main" java.lang.OutOfMemoryError: Java heap space ”错误的解决办法
- Gnostice PDFOne For JAVA Crack
- 当年的Java考试:JAVA&移动应用&大数据-大三-社区疫苗接种管理系统(全部源码·保姆式呵护)
- 【java】Java生成微信小程序二维码
- Simple Logging Facade for Java (SLF4J)作用(java日志框架)
- 【华为OD机试 2023】模拟商场优惠打折(C++ Java JavaScript Python)
- JAVA编程:java环境安装和helloworld
- Java 8 中的 java.util.Map#computeIfAbsent
- Java 异常解决之java.lang.IllegalArgumentException: Comparison method violates its general contract!
- mysql-connector-java与Mysql、Java的对应版本
- 【java】Java并发编程系列-基础知识(非常详细哦)