程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

Java中的网络编程如何理解——精简

发布于2022-08-07 19:50     阅读(236)     评论(0)     点赞(8)     收藏(5)


目录

引言

网络通信的三要素 

IP 

IP地址操作类InetAddress 

端口号(了解) 

协议 

UDP通信 

TCP通信 

实现同时接收多个客户端 

线程池优化 


 

引言

         经过前面的课程,我们已经大概地了解到多线程的知识了,不知道大家是否已经掌握了呢?如果已经掌握了的话,那么我们今天就开始学习Java中的网络编程的相关知识,那么什么是网络编程呢?网络编程是可以让程序与网络上的其他设备中的数据进行数据交互。常见的通信模式有两种形式:Client-Server(CS)、Browser/Server(BS)。接下来我们将要学习的知识是网络通信的三要素、UDP通信、TCP通信。

 

网络通信的三要素 

关键的三要素:

  • IP地址:设备在网络中的地址。
  • 端口:应用程序在设备中唯一的标识。
  • 协议:数据库在网络中传输的规则,常见的协议有UDP协议和TCP协议。

(在通信过程中通过IP地址寻找设备,端口确定设备中的应用中的程序。) 

IP 

IP地址形式:

  • 公网地址和私有地址(局域网使用)
  • 192.168.开头的就是常见的局域网地址,范围即为192.168.0.0--192.168.255.255,专门为组织机构内部使用。

IP常用命令:

  • ipconfig:查看本机IP地址
  • ping IP地址:检查网路是否连通

特殊IP地址:

  • 本机IP:127.0.0.1或者localhost:称为回送地址也可称为本地回环地址,只会寻找当前所在本机。 

IP地址操作类InetAddress 

InetAddress常用API

名称说明
public static InetAddress getLocalHost()返回本主机的地址对象
public static InetAddress getByName(String host)得到指定主机的IP地址对象,参数是域名或者IP地址
public string getHostName()获取此IP地址的主机名
public string getHostAddress()返回IP地址字符串
public boolean isReachable(int timeout)在指定毫秒内连通该IP地址对应的主机,连通返回true

 

  1. InetAddress ip1 = InetAddress.getLocalHost();
  2. //获取IP地址字符串
  3. System.out.println(ip1.getHostAddress());
  4. //返回IP地址主机名
  5. System.out.println(ip1.getHostName());
  6. //得到指定主机的IP地址对象
  7. InetAddress ip2 = InetAddress.getByName("www.bilibili.com");
  8. //返回IP地址主机名
  9. System.out.println(ip2.getHostName());
  10. //获取IP地址字符串
  11. System.out.println(ip2.getHostAddress());
  12. //得到指定主机的IP地址对象
  13. InetAddress ip3 = InetAddress.getByName("111.6.174.2");
  14. //返回IP地址主机名
  15. System.out.println(ip3.getHostName());
  16. //获取IP地址字符串
  17. System.out.println(ip3.getHostAddress());
  18. //5秒后连通
  19. System.out.println(ip3.isReachable(5000));

 

端口号(了解) 

端口号:标识正在计算机设备上运行的进程(程序),被规定为一个16位的二进制,范围是0-65535。

端口类型:0-1023,被预先定义的知名应用占用(如:HTTP占用80,FTP占用21)。

注册端口:1024-49151,分配给用户进程或某些应用程序。(如:Tomcat占用8080,MySQL占用3306)。

动态端口:49152-65535,之所以称为动态端口,是因为它一般不固定分配某种进程,而是动态分配。

注意:我们自己开发的程序选择注册端口,且一个设备中不能出现两个程序的端口号一样,否则出错。

协议 

传输层的两个常见协议:

  • TCP:传输控制协议
  • UDP:用户数据协议

TCP协议特点:

  • 使用TCP协议,必须双方先建立连接,它是一种面向连接的可靠通信协议
  • 传输前,采用“三次握手”方式建立连接,所以是可靠的
  • 在连接中可进行大数据量的传输
  • 连接、发送数据都需要确认,且传输完毕后,还需释放已建立的连接,通信效率较低

TCP协议通信场景:

  • 对信息安全要求较高的场景,如:文件下载、金融等数据通信

UDP协议:

  • UDP是一种无连接、不可靠传输的协议
  • 将数据源IP、目的地IP和端口封装成数据包,不需要建立连接
  • 每个数据包的大小限制在64KB内
  • 发送不管对方是否准备好,接收方收到也不确认,故是不可靠的
  • 可以广播发送,发送数据结束时无需释放资源,开销小,速度快

UDP协议通信场景:

语言通话、视频通话等。

 

 

UDP通信 

DatagramPacket:数据包对象

构造器说明
public DatagramPacket(byte[ ]buf,int length,InetAddress address,int port)

创建发送端数据包对象
buf:要发送的内容,字节数组

length:要发送内容的字节长度

address:接收端的

IP地址对象

port:接收端的端口号

public DatagramPacket(byte [ ] buf, int length  )

创建接收端的数据包对象

buf:用来存储接收的内容

length:能够接收内容的长度

 DatagramSocket:发送端和接收端对象

构造器说明
public DatagramSocket( )创建发送端的socket对象,系统会随机分配一个端口号
public DatagramSocket(int port)创建接收端的socket对象并指定端口号
方法说明
public void send (DatagramPacket dp)发送数据包
public void receive (DatagramPacket p)接收数据包

        为了更好的理解DatagramSocket和DatagramPacket,我们可以形象的把UDP形象的想象成“网购”,其中DatagramPacket就代表我们想要网购的商品,虽然这是我们买的,但是我们肯定是没有办法亲自去把商品拿走,因此就需要快递的运送,而DatagramSocket就是充当这个角色。商家将需要邮寄的商品通过DatagramPacket封装起来,然后再通过快递DatagramSocket将该商品派送到买家的手中。

  1. //客户端
  2. public static void main(String[] args) throws Exception{
  3. DatagramSocket socket = new DatagramSocket();
  4. byte [] buffer = "你好,我是石原里美!".getBytes();
  5. DatagramPacket packet = new DatagramPacket(buffer,buffer.length, InetAddress.getLocalHost(),9999);
  6. socket.send(packet);
  7. socket.close();
  8. }
  1. //服务端
  2. public static void main(String[] args) throws Exception{
  3. DatagramSocket socket = new DatagramSocket(9999);
  4. byte[] buffer = new byte[1024];
  5. DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
  6. socket.receive(packet);
  7. int len = packet.getLength();//返回获取数据的长度
  8. String s = new String(buffer,0,len);
  9. System.out.println(s);
  10. socket.close();
  11. }

注意:服务端需要先启动,等待客户端向服务端传送数据。

 

TCP通信 

Socket

构造器说明
public Socket(String host , int port)
 
创建发送端的Socket对象与服务端连接,参数为服务端程序的ip和端口。
 

 

方法说明
OutputStream getOutputStream( )获得字节输出流对象
InputStream getInputStream()获得字节输入流对象

ServerSocket(服务端)

构造器说明
public ServerSocket(int port)注册服务端端口
方法说明
public Socket accept()

等待接口客户端的Socket通信连接,连接成功返回Socket对象与客户端建立端与端通信

  1. //客户端
  2. public static void main(String[] args) throws Exception{
  3. Socket socket = new Socket("172.0.0.1",7777);
  4. OutputStream os = socket.getOutputStream();
  5. //通过打印输入流可以更高效
  6. PrintStream printStream = new PrintStream(os);
  7. printStream.println("你好,我是石原里美!");
  8. printStream.flush();
  9. }
  10. }
  1. public static void main(String[] args) throws Exception{
  2. ServerSocket serverSocket = new ServerSocket(7777);
  3. Socket socket = serverSocket.accept();
  4. InputStream is = socket.getInputStream();
  5. //将字节输入流转化位字符输入流,再封装位缓冲字符输入流
  6. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
  7. String s ;
  8. while ((s = bufferedReader.readLine())!=null){
  9. System.out.println(socket.getLocalSocketAddress()+s);
  10. }
  11. }

 

实现同时接收多个客户端 

如果想要实现同时接收多个客户端的话,就需要使用多线程的知识,创建多个服务端。

首先创建一个类继承Thread,用于创建多线程:

  1. public class ServerThread extends Thread{
  2. private Socket socket;
  3. public ServerThread(Socket socket) {
  4. this.socket = socket;
  5. }
  6. //中间内容不在此赘述
  7. @Override
  8. public void run() {
  9. try {
  10. InputStream is = socket.getInputStream();
  11. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
  12. String s ;
  13. while ((s = bufferedReader.readLine())!=null){
  14. System.out.println(socket.getLocalSocketAddress()+s);
  15. }
  16. } catch (IOException e) {
  17. e.printStackTrace();
  18. }
  19. }
  20. }

 客户端代码:

  1. public static void main(String[] args) throws Exception{
  2. Socket socket = new Socket("172.0.0.1",7777);
  3. OutputStream os = socket.getOutputStream();
  4. PrintStream printStream = new PrintStream(os);
  5. Scanner sc = new Scanner(System.in);
  6. while (true) {
  7. String s = sc.next();
  8. printStream.println(s);
  9. printStream.flush();
  10. }
  11. }

服务端代码:

  1. public static void main(String[] args) throws Exception{
  2. ServerSocket serverSocket = new ServerSocket(7777);
  3. while (true) {
  4. Socket socket = serverSocket.accept();
  5. new ServerThread(socket).start();
  6. }
  7. }

具体操作:在运行单个服务端代码之后,运行多个客户端代码即可实现同时接收多个客户端。

 

线程池优化 

通过前面的知识,我们了解到每一次都创建一个线程会影响系统的效率,因此需要通过线程池来控制线程的数量,若对线程池不理解的可以看这篇文章:

Java中的多线程如何理解 

相对之前需要将线程类更改一下,需要写一个实现Runnable接口的线程类。

  1. public class ServerRunnable implements Runnable{
  2. private Socket socket;
  3. @Override
  4. public void run() {
  5. }
  6. }

最后则是需要在服务端作出修改,定义一个线程池:

  1. public class ServerData {
  2. private static ExecutorService pool = new ThreadPoolExecutor(3,5,5, TimeUnit.SECONDS,new ArrayBlockingQueue<>(3),
  3. Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
  4. public static void main(String[] args) throws Exception{
  5. ServerSocket serverSocket = new ServerSocket(7777);
  6. while (true) {
  7. Socket socket = serverSocket.accept();
  8. ServerRunnable target = new ServerRunnable(socket);
  9. pool.execute(target);
  10. }
  11. }
  12. }

创作不易,给个三连 

 

 

原文链接:https://blog.csdn.net/weixin_50635856/article/details/125967888



所属网站分类: 技术文章 > 博客

作者:我是个大美女

链接:http://www.javaheidong.com/blog/article/472569/af6002036aa0fd1e3099/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

8 0
收藏该文
已收藏

评论内容:(最多支持255个字符)