Java中的网络编程以及TCP\UDP协议程序实例 ╰半夏微凉° 2022-04-05 04:40 147阅读 0赞 ### 文章目录 ### * * * * 一、网络编程 * 二、程序实例 * * * 1、UDP协议 发送接收实例 * 2、UDP协议 利用多线程实现自己和自己聊天的程序实例 * 3、TCP协议 发送接收实例 * 4、TCP协议 发送接收文件实例 * 5、TCP协议 多线程实现一个服务器接入多个客户端实例 #### 一、网络编程 #### 1、网络编程的三要素: a) IP地址:网络中计算机的唯一标识 i. 常用的Dos命令 1. ipconfig:查看本机的IP地址 2. ping IP地址:测试本机与指定IP地址的通信 ii. IP地址的分类 A、1.0.0.1—127.255.255.254 10.X.X.X私有地址(私有地址:互联网上不使用,仅局域网使用) 第一号段为网络号段,后三段为主机号段 B、128.0.0.1—191.255.255.254 172.16.0.0—172.31.255.255私有地址 169.254.X.X保留地址 前两号段为网络号段,后两段为主机号段 C、192.0.0.1—223.255.255.254 192.168.X.X私有地址 前三号段为网络号段,最后一段为主机号段 D、224.0.0.1—239.255.255.254 E、240.0.0.1—247.255.255.254 iii. 特殊IP地址 1. 127.0.0.1 回环地址(表示本机) 2. X.X.X.255 广播地址 3. X.X.X.0 网络地址 b) 端口: i. 物理端口:网卡口 ii. 逻辑端口:正在运行程序的标识 有效端口:0~65535 系统端口0~1024 c) 协议: i. UDP:将数据源和目的地封装成数据包,不需要建立连接,每个数据报的大小限制在64k; 因无连接,属于不可靠协议,但运行速度快 ii. TCP:先建立连接,形成传输数据的通道,可以在连接中进行大量数据传输, 通过三次握手完成连接,是可靠协议,效率稍低 2. InetAddress类 表示互联网协议的IP地址 a) 此类无构造方法 如果一个类无构造方法: i. 成员全部是静态的(Math,Arrays,Collections) ii. 单例设计模式(Runtime) iii. 类中有静态方法,返回该类的对象(InetAddress类) b) 成员方法 i. public static InetAddress getByName(String host) 根据主机名或者IP地址的字符串表达形式获取IP地址对象 ii. public String getHostName() 根据IP地址对象获取主机名 iii. public String getHostAdderess() 根据IP地址对象获取IP地址 3. Socket:网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字 a) 原理机制 i. 通信两端都有Socket ii. 网络通信其实就是Socket间的通信 iii. 数据在两个Socket之间通过IO传输 4. UDP协议 UDP协议中的Socket对象是DatagramSocket对象 a) 发送数据 i. 创建发送端Socket对象 ii. 创建数据,并将数据打包 数据包构造方法:public DatagramPacket(byte \[\] buf, int length, InetAddress address, int port) buf为数据数组,length为数据长度,address为数据IP地址,port为数据端口 iii. 调用Socket对象的发送方法来发送数据包 public void send(DatagramPacket p) iv. 释放资源 b) 接收数据 i. 创建接收端Socket对象(创建对象时需要指定端口号) ii. 创建一个数据包(接收容器) 数据包构造方法public DatagramPacket(byte \[\] buf, int length) iii. 调用Socket对象的接收方法接收数据 public void receive(DatagramPacket p) iv. 解析数据 public byte \[\] getData() 获取数据缓冲区 public int getLength() 获取数据的实际长度 public InetAddress getAddress() 获取数据发送端的IP地址对象 v. 释放资源 c) 下面给出了传输实例 5. TCP协议 a) 发送 i. 创建TCP客户端Socket对象 ii. 获取输出流,写数据 iii. 释放资源 b) 接收 i. 创建服务器端ServerSocket对象 ii. 监听客户端连接 iii. 获取输入流,读取数据 iv. 释放资源 #### 二、程序实例 #### ###### 1、UDP协议 发送接收实例 ###### 发送端 package test01_UDP_ReceiveSend; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /* *UDP发送数据 * i. 创建发送端Socket对象 * ii. 创建数据,并将数据打包 * 数据包构造方法:public DatagramPacket(byte [] buf, * int length, InetAddress address, int port) * buf为数据数组,length为数据长度,address为数据IP地址,port为数据端口 * iii.调用Socket对象的发送方法来发送数据包 * public void send(DatagramPacket p) * iv. 释放资源 */ public class SendDemo { public static void main(String[] args) throws IOException { //创建Socket对象 DatagramSocket ds=new DatagramSocket(); //创建数据并打包,包括数据数组、数据长度、接收端地址和接收端端口号 byte []bys="HelloWorld".getBytes(); DatagramPacket dp=new DatagramPacket(bys, 0, bys.length, InetAddress.getByName("10.128.245.238"), 12345); //发送数据 ds.send(dp); //释放资源 ds.close(); } } 接收端 package test01_UDP_ReceiveSend; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; /* * i. 创建接收端Socket对象(创建对象时需要指定端口号) * ii. 创建一个数据包(接收容器) * 数据包构造方法public DatagramPacket(byte [] buf, int length) * iii. 调用Socket对象的接收方法接收数据 * public void receive(DatagramPacket p) * iv. 解析数据 * public byte [] getData() 获取数据缓冲区 * public int getLength() 获取数据的实际长度 * public InetAddress getAddress() 获取数据发送端的IP地址对象 * v. 释放资源 * 多次启动会报错: * java.net.BindException: Address already in use: Cannot bind * 原因: * 多次启动端口被占用 */ public class ReceiveDemo { public static void main(String[] args) throws IOException { //创建Socket对象 DatagramSocket ds=new DatagramSocket(12345); //创建包裹 byte[] bys=new byte[1024]; DatagramPacket dp=new DatagramPacket(bys, bys.length); //接收数据 ds.receive(dp); //解析数据 String ip=dp.getAddress().getHostAddress(); String s=new String(dp.getData(), 0, dp.getLength()); System.out.println("ip:"+ip+" Data:"+s); //释放资源 ds.close(); } } ###### 2、UDP协议 利用多线程实现自己和自己聊天的程序实例 ###### 测试代码 package test02_UDP_Chat; import java.io.IOException; import java.net.DatagramSocket; /* * 通过多线程实现聊天小程序 */ public class ChatDemo { public static void main(String[] args) throws IOException { DatagramSocket dsSend =new DatagramSocket(); DatagramSocket dsReceive =new DatagramSocket(12345); SendThread st=new SendThread(dsSend); ReceiveThread rh=new ReceiveThread(dsReceive); Thread t1=new Thread(st); Thread t2=new Thread(rh); t1.start(); t2.start(); } } 利用线程实现接收端 package test02_UDP_Chat; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; //接收端 public class ReceiveThread implements Runnable { private DatagramSocket ds; public ReceiveThread(DatagramSocket ds) { this.ds=ds; } public void run() { try { while(true) { byte []b=new byte[1024]; DatagramPacket dp=new DatagramPacket(b, b.length); ds.receive(dp); String ip=dp.getAddress().getHostAddress(); String data=new String(dp.getData(), 0, dp.getLength()); System.out.println("ip:"+ip+" Data:"+data); //因为要持续接收所以不释放资源 //ds.close(); } } catch (IOException e) { e.printStackTrace(); } } } 利用线程实现发送端 package test02_UDP_Chat; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; //发送端 public class SendThread implements Runnable { private DatagramSocket ds; public SendThread(DatagramSocket ds) { this.ds=ds; } public void run() { BufferedReader br=new BufferedReader(new InputStreamReader(System.in)) ; String line=null; try { while((line=br.readLine()) !=null) { //当接收到886时结束发送 if(line.equals("886")) { break; } byte []b=line.getBytes(); //注意发送端端口号要和接收端端口号相同 DatagramPacket dp=new DatagramPacket(b, 0, b.length, InetAddress.getByName("10.128.245.238"), 12345); ds.send(dp); } ds.close(); } catch (IOException e) { e.printStackTrace(); } } } ###### 3、TCP协议 发送接收实例 ###### 发送端 package test03_TCP_ReceiveSend; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; /* * TCP协议的发送数据 * 1、创建发送端的Socket对象,这一步如果成功说明连接建立成功了。 * 2、获取输出流,写数据 * 3、释放资源 */ public class SendDemo { public static void main(String[] args) throws IOException { //创建发送端的Socket对象,2种方法 //Socket(InetAddress address , int port) //Socket(String host ,int port) //Socket s=new Socket(InetAddress.getByName("10.128.245.238"), 12345); Socket s=new Socket("10.128.245.238",12345); //获取输出流,写数据 OutputStream os=s.getOutputStream(); os.write("HelloWorld,TCP".getBytes()); //获取输入流,当接收数据成功后服务器给的反馈 InputStream is =s.getInputStream(); byte []b=new byte[1024]; int len=is.read(b); //阻塞 String str=new String(b, 0, len); System.out.println("client:"+str); //释放资源 s.close(); } } 接收端 package test03_TCP_ReceiveSend; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; /* * TCP协议接收数据: * 1、创建接收端Socket对象 * 2、监听客户端连接,返回一个Socket对象 * 3、获取输入流,读取数据显示在控制台 * 4、释放资源 */ public class ReceivedDemo { public static void main(String[] args) throws IOException { //创建发送端对象 //ServerSocket(int port) ServerSocket ss = new ServerSocket(12345); //监听客户端连接,返回一个Socket对象 //public Socket accept(); Socket s=ss.accept(); //阻塞 //获取输入流并将读取数据显示在控制台 InputStream is=s.getInputStream(); byte [] b= new byte[1024]; int len=is.read(b); //阻塞 String str=new String(b,0,len); String ip=s.getInetAddress().getHostAddress(); System.out.println("Data:"+str+"IP:"+ip); //获取输出流,接收到字节数据后需要给一个反馈 OutputStream os = s.getOutputStream(); os.write("服务器已接收数据".getBytes()); //释放资源 s.close(); ss.close(); } } ###### 4、TCP协议 发送接收文件实例 ###### 发送端 package test04_TCP_file; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; /* * 将文件数据读入,并发送到服务器端 * 以字符串的形式,每次读取文件的一行内容并发送 * * 加入反馈信息,结果没反应,原因: * 读取文本文件时以null作为结束信息,但是传递信息时,null不会被传递, * 所以服务器并不确定结束了,而客户端一直在等服务器给反馈,所以最终就互相等待了 * * 解决; * 1、再多写一条数据作为结束标志,当客户端读取到此数据时意味着客户端读取文件结束了,服务器端接收到结束标志时也结束运行 * 此方法有一个弊端,如果结束标志在文件中也存在,文件便会读取不全 * 2、Socket对象提供了一个终止功能,会通知服务器结束传送 * public void shutdownOutput() 关闭输出流 * public void shutdownInput() 关闭输入流 */ public class ClientDemo { public static void main(String[] args) throws IOException { Socket s=new Socket("10.128.245.238",12345); BufferedReader br=new BufferedReader(new FileReader("D:\\jee-2018-09\\Net\\src\\test01_UDP_ReceiveSend\\ReceiveDemo.java")); BufferedWriter bw=new BufferedWriter( new OutputStreamWriter(s.getOutputStream())); String line=null; while((line=br.readLine())!=null) { bw.write(line); bw.newLine(); bw.flush(); } //告诉服务器端传送结束 s.shutdownOutput(); BufferedReader brClient=new BufferedReader( new InputStreamReader(s.getInputStream())); String client=brClient.readLine(); System.out.println(client); br.close(); s.close(); } } 接收端 package test04_TCP_file; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; //接收客户端发送的数据,并存入到文件中 // 每次接收一行并以字符串的格式写入到文件中 public class ServerDemo { public static void main(String[] args) throws IOException { ServerSocket ss=new ServerSocket(12345); Socket s=ss.accept(); BufferedWriter bw= new BufferedWriter(new FileWriter("a.txt")); BufferedReader br=new BufferedReader(new InputStreamReader (s.getInputStream())); String line=null; while((line=br.readLine())!=null) { bw.write(line); bw.newLine(); bw.flush(); } BufferedWriter bwServer=new BufferedWriter(new OutputStreamWriter (s.getOutputStream())); bwServer.write("文件上传成功"); bwServer.newLine(); bwServer.flush(); bw.close(); s.close(); ss.close(); } } ###### 5、TCP协议 多线程实现一个服务器接入多个客户端实例 ###### 服务器端测试类 package test05_TCP_Thread; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class Server { public static void main(String[] args) throws IOException { ServerSocket ss=new ServerSocket(12345); while(true) { Socket s=ss.accept(); ServerThread st=new ServerThread(s); new Thread(st).start(); } } } 多线程实现服务器端 package test05_TCP_Thread; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; public class ServerThread implements Runnable { private Socket s; public ServerThread(Socket s) { this.s=s; } public void run() { try { //为了区别不同客户端发送的文件,服务器针对不同客户端采用不同的命名方式 String newName = System.currentTimeMillis()+".java"; BufferedWriter bw= new BufferedWriter(new FileWriter(newName)); BufferedReader br=new BufferedReader(new InputStreamReader (s.getInputStream())); String line=null; while((line=br.readLine())!=null) { bw.write(line); bw.newLine(); //不论传输字节流还是字符流都要刷新一下以免最后的数据漏传 bw.flush(); } BufferedWriter bwServer=new BufferedWriter(new OutputStreamWriter (s.getOutputStream())); bwServer.write("文件上传成功"); bwServer.newLine(); bwServer.flush(); bw.close(); s.close(); }catch(IOException e){ e.printStackTrace(); } } } 客户端 package test05_TCP_Thread; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; public class Client { public static void main(String[] args) throws IOException { Socket s=new Socket("10.128.245.238",12345); BufferedReader br=new BufferedReader(new FileReader("D:\\jee-2018-09\\Net\\src\\test01_UDP_ReceiveSend\\ReceiveDemo.java")); BufferedWriter bw=new BufferedWriter( new OutputStreamWriter(s.getOutputStream())); String line=null; while((line=br.readLine())!=null) { bw.write(line); bw.newLine(); bw.flush(); } //告诉服务器端传送结束 s.shutdownOutput(); BufferedReader brClient=new BufferedReader( new InputStreamReader(s.getInputStream())); String client=brClient.readLine(); System.out.println(client); br.close(); s.close(); } }
相关 网络编程中,Java连接池的问题实例 在Java网络编程中,连接池是一个常见的优化手段,用于管理和复用数据库连接。以下是一个关于连接池问题的实例: 1. **场景描述**:假设我们正在开发一个电子商务网站,需要频 川长思鸟来/ 2024年09月18日 14:15/ 0 赞/ 6 阅读
相关 处理Java网络编程中的异常问题实例 在Java网络编程中,常见的异常包括SocketException、IOException和ConnectionRefusedException等。以下是一个处理这些异常的实例 一时失言乱红尘/ 2024年09月11日 10:33/ 0 赞/ 19 阅读
相关 探讨Java中网络编程中的连接问题实例 在Java的网络编程中,连接问题是常见的一个环节。以下是一个关于连接问题的实例: 假设我们正在开发一个基于HTTP的Web服务。这个服务需要与客户端建立连接才能进行交互。 ╰+攻爆jí腚メ/ 2024年09月05日 17:33/ 0 赞/ 21 阅读
相关 socket编程-- 基于TCP协议的网络程序 [socket编程-- 基于TCP协议的网络程序][socket_-- _TCP] 下图是基于TCP协议的客户端/服务器程序的一般流程: TCP协议通讯流程 [! 快来打我*/ 2022年08月01日 11:21/ 0 赞/ 188 阅读
相关 Unix网络编程实例:获取时间网络程序 TCP获取时间网络程序,Server端:daytimetcpsrv.c include <stdio.h> include <stdlib.h> 朴灿烈づ我的快乐病毒、/ 2022年06月18日 00:18/ 0 赞/ 218 阅读
相关 Java 网络编程API以及实例 Java 网络编程 网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来。 java.net包中J2SE的API包含有类和接口,它们提供低层次的通 阳光穿透心脏的1/2处/ 2022年06月15日 06:42/ 0 赞/ 181 阅读
相关 Java网络编程(二)-基于http协议的网络编程 本篇博客介绍另一种编程方式-基于http协议的网络编程,实现不同主机之间的通信。下面从HTTP、URL、URLConnection给出基于http协议的网络编程。 1、URL ゝ一世哀愁。/ 2022年06月13日 07:16/ 0 赞/ 162 阅读
相关 网络,以及网络协议 之前负责一个项目的时候出现这样一个问题,当我选用兼容模式的时候,某个Iframe嵌套的模块可以显示,但是,当我选择的是360极速模式的时候,就显示不出来,找了很久的原因,才发现 系统管理员/ 2022年05月30日 08:36/ 0 赞/ 172 阅读
相关 Java中的网络编程以及TCP\UDP协议程序实例 文章目录 一、网络编程 二、程序实例 1、UDP协议 发送接收实例 ╰半夏微凉°/ 2022年04月05日 04:40/ 0 赞/ 148 阅读
还没有评论,来说两句吧...