Loading... ## 概述 概述:网络通信协议下,不同计算机上运行的程序,可以进行数据传输 例如,A电脑中的飞秋,发送消息给B电脑中的飞秋,需要哪些条件才能发送嗯? IP地址 - 设备在网络中的地址,是唯一的标识。 端口 - 应用程序在设备中唯一的标识。 协议 - 数据在网络中传输的规则,常见的协议有UDP协议和TCP协议。 ## IP ip:全称为:互联网协议地址,也称IP地址,是分配给上网设备的数字标签,常见的IP分类为:ipv4和ipv6  - IPv4: 是网际协议开发过程中的第四个修订版本,也是此协议第一个被广泛部署的版本。IPv4是互联网的核心,也是使用最广泛的网际协议版本,其后继版本为IPv6,直到2011年,IANA IPv4位址完全用尽时,IPv6仍处在部署的初期。 - IPv6:由于IPv4最大的问题在于网络地址资源有限,严重制约了互联网的应用和发展。IPv6的使用,不仅能解决网络地址资源数量的问题,而且也解决了多种接入设备连入互联网的障碍 [1] 。 互联网数字分配机构(IANA)在2016年已向国际互联网工程任务组(IETF)提出建议,要求新制定的国际互联网标准只支持IPv6,不再兼容IPv4。 > 具体可以通过百度百科了解。 常用命令: - ipconfig:查看本机IP - ping IP地址:检查网络是否连通 我们ping一下博客地址,其中47.106.67.159就是我服务器电脑的ip了。可以检测当前电脑与服务器之间是否畅通,同时确定服务器的IP。  特殊IP地址: - 127.0.0.1:回送地址也称本地回环地址,可以代表本机的IP地址,一般是用来做测试使用。 ## InetAddress 为了方便我们对IP地址的获取和操作,java提供了一个类InetAddress供我们使用 InetAddress:此类表示Internet协议(IP)地址 具体查看JDK的官方API文档 ## 端口 端口:要用程序在设备中的唯一标识 端口号:用两个字节表示的数据,它的取值范围是0~65535,其中0~1023之间的端口号用于一些知名的网络服务或者应用。我们自己使用1024以上的端口号 注意:一个端口号只能被一个应用程序使用。 ## 协议 协议:计算机网络中,连接和通信的规则被称为网络通信协议 ### UDP协议 - UDP是面向无连接通信协议。速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据。 - 不管你有没有建立连接,他都会发送出去。 - 常用于:传递音频、数据、普通数据等 ### TCP协议 - TCP协议是面向连接的通信协议 - 速度慢,没有大小限制,数据安全 ## 总结 网络编程:就是让两台计算机进行数据交互 网络编程三要素 - IP:设备在网络中唯一的标识 - 端口号:应用程序在设备中唯一的标识 - 协议:数据在传输过程中遵循的规则 ## UDP通信程序 ### UDP发送数据: 步骤: - 创建发送端的DatagramSocket对象 - 创建数据,并把数据打包进箱子(DatagramPacket) - 调用DatagramSocket对象的方法发送数据 - 释放资源 代码示例。 ```java public class ClientDemo { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(); //设置要传输的数据,并转化为byte类型,不能直接穿字符串 String s = "你家孩子被录取了"; byte[] bytes = s.getBytes(); //创建主机且命名为localhost InetAddress address = InetAddress.getByName("localhost"); //设置端口 int port = 1000; //保存进箱子 DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port); socket.send(packet); socket.close(); } } ```  运行结果为空白,我们没有设置接收端,UDP协议只管发,收不收得到都不管。 ### UDP接收数据 步骤: - 创建接收端的DatagramSocket对象 - 创建一个箱子,用于接收数据 - 调用DatagramSocket的方法接收数据并将数据放进箱子中保存 - 解析数据,在控制台显示 - 释放资源 ```java public class ServeDemo { public static void main(String[] args) throws IOException { //表示从1000端口接受数据 DatagramSocket socket = new DatagramSocket(1000); //给箱子设置一个byte数组进行接收 byte[] bytes = new byte[1024]; DatagramPacket packet = new DatagramPacket(bytes, bytes.length); socket.receive(packet); //在控制台打印数据 System.out.println(new String(bytes)); //我们也可以通过getData()方法将箱子里的数据重新拿出,一般不需要 byte[] data = packet.getData(); System.out.println(new String(data)); //记得释放资源 socket.close(); } } ``` 我们运行起来,发现程序正在运行,但是没有打印出任何东西。  这很正常,因为我们并没有发送数据给它呀,这时我们保持接收端不动,去运行前面已经写好的发送端,他们端口都是1000。  我们看到效果已经出现了! - 如果你先运行了发送端,它就已经把数据发送出去了,你此时再运行接收端就没有效果了。 - 如果接收端启动之后,没有收到数据,那么它就会死等(阻塞)。也就是它会运行到示例代码中的第9行就等在了那里。 - 在接收数据的时候,需要调用一个getLength方法,表示接收到了多少字节。这里我们使用了1024个字节去接收数据,所以导致我们接收到数据后,后面带了很多空格,具体看下图。所以我们在打印输出中传入长度即可。  ```java System.out.println(new String(bytes,0,packet.getLength())); ``` ## UDP通信程序练习 需求: - UDP发送数据:数据来自键盘录入,直到输入的数据是886,发送数据结束。 - UPD接收数据:因为接收端不知道发送端什么时候停止发送,所以我们采用死循环接收。 ```java public class Serve { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(996); while (true) { byte[] bytes = new byte[1024]; DatagramPacket packet = new DatagramPacket(bytes, bytes.length); socket.receive(packet); System.out.println(new String(bytes, 0, packet.getLength())); } } } ``` ```java public class Client { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(); Scanner sc = new Scanner(System.in); while (true) { String s = sc.nextLine(); if ("886".equals(s)){ break; } byte[] bytes = s.getBytes(); InetAddress address = InetAddress.getByName("127.0.0.1"); int port = 996; DatagramPacket packet = new DatagramPacket(bytes,bytes.length,address,port); socket.send(packet); } socket.close(); } } ``` ## UDP三种通信方式 - 单播,一对一 - 组播,一对多 - 广播,一对所有 ### UDP通信组播代码实现 组播地址:224.0.0.0~239.255.255.255 其中224.0.0.0~224.0.0.255为预留的组播地址 组播的发送端跟单播类似,也就是跟我们已经演示过的代码类似。但是在单播中,我们是发给指定IP的电脑,在组播中,是发给组播地址。 我们可以看到下面的代码中,我们开头创建了MulticastSocket对象并传入了端口,后面再加入组IP接收数据。这就是组播的接收端示例代码: ```java public class Serve2 { public static void main(String[] args) throws IOException { MulticastSocket multicastSocket = new MulticastSocket(10000); byte[] bytes = new byte[1024]; DatagramPacket packet = new DatagramPacket(bytes, bytes.length); //把当前计算机绑定一个组播地址,表示添加到这一组中 //注意,这里要跟发送端设置的IP一样 multicastSocket.joinGroup(InetAddress.getByName("224.0.1.0")); multicastSocket.receive(packet); System.out.println(new String(bytes,0,packet.getLength())); } } ``` 发送端: ```java public class Client2 { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(); String s = "我是乐心湖啊"; byte[] bytes = s.getBytes(); //设置IP InetAddress address = InetAddress.getByName("224.0.1.0"); int port = 10000; DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port); socket.send(packet); socket.close(); } ``` 测试,只要你的小伙伴都设置了这个IP和端口(即使用了示例中的接收端),你运行发送端就可以发送 “我是乐心湖啊” 给他们了。 ### UDP通信广播代码实现 广播地址:255.255.255.255 (必须) 接收端跟单播没有两样。 ```java public class Serve3 { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(10000); byte[] bytes = new byte[1024]; DatagramPacket packet = new DatagramPacket(bytes, bytes.length); socket.receive(packet); System.out.println(new String(bytes, 0, packet.getLength())); socket.close(); } } ``` ```java public class Client3 { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(); String s = "是广播哦"; byte[] bytes = s.getBytes(); //设置IP InetAddress address = InetAddress.getByName("255.255.255.255"); int port = 10000; DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port); socket.send(packet); socket.close(); } } ``` ## TCP通信程序 ### 原理: - TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象。 - **通信之前必须要建立连接** - 通过Socket产生IO流来进行网络通信 ### TCP发送数据: 步骤: 1. 创建客户端的Socket对象与指定服务端连接 , Socket(String host,int port) 2. 获取输出流,写数据 OutputStream getOutputStream() 3. 释放资源,void close() 此时运行客户端必然报错,因为我们没有写服务端,而TCP协议**通信之前必须要建立连接** ```java public class Client4 { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.0.1", 996); OutputStream outputStream = socket.getOutputStream(); outputStream.write("hello,leixnhu".getBytes()); outputStream.close(); socket.close(); } } ``` ### TCP接收数据 步骤: 1. 创建服务端的Socket对象(ServerSocket) ServerSocket(int port) 2. 监听客户端连接,返回一个Socket对象 Socket.accept() 3. 获取输入流,读数据,并把数据显示在控制台上 InputSteam getInputStream() 4. 释放资源 void close() ```java public class Serve4 { public static void main(String[] args) throws IOException { ServerSocket socket = new ServerSocket(996); Socket accept = socket.accept(); InputStream inputStream = accept.getInputStream(); int a; while ((a = inputStream.read())!=-1){ System.out.print((char) a); } inputStream.close(); socket.close(); } } ``` ### 注意: - accept方法是阻塞的,为了等待客户端连接 - 客户端创建对象连接服务器,此时是通过三次握手协议保证跟服务器之间的连接。 - 针对客户端来讲,是往外写的,所以是输出流 - 针对服务器来讲,是往里读的,所以是输入流 - read方法也是阻塞的 - 在关流的时候,还多了一个往服务器写结束标记的动作 - 最后一步断开连接,通过四次挥手协议保证连接终止 <hr class="content-copyright" style="margin-top:50px" /><blockquote class="content-copyright" style="font-style:normal"><p class="content-copyright">版权属于:乐心湖's Blog</p><p class="content-copyright">本文链接:<a class="content-copyright" href="https://www.xn2001.com/archives/405.html">https://www.xn2001.com/archives/405.html</a></p><p class="content-copyright">声明:博客所有文章除特别声明外,均采用 <a href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" target="_blank" rel="nofollow noopener noopener" one-link-mark="yes">CC BY-SA 4.0 协议</a> ,转载请注明出处!</p></blockquote> 腾讯云社区邀请各位技术博主加入,福利多多噢! Last modification:June 5th, 2020 at 11:31 am © 允许规范转载 Support 如果觉得我的文章对你有用,请随意赞赏 ×Close Appreciate the author Sweeping payments Pay by AliPay Pay by WeChat