热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java笔记——网络编程

目录计算机网络的定义网络通信协议的分类:网络编程的目的:IP端口号TCP与UDPTCP的三次握手(建立连接)TCP的四次挥手

目录

          • 计算机网络的定义
          • 网络通信协议的分类:
          • 网络编程的目的:
        • IP
        • 端口号
        • TCP与UDP
            • TCP的三次握手(建立连接)
            • TCP的四次挥手(断开连接)
        • TCP实例
            • 实例一、传输字符串
            • 实例二、传输文件
        • UDP实例


计算机网络的定义

计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。


网络通信协议的分类:

网络通信协议,可以比喻成大家都说普通话,所以我们可以正常的交流。但如果我们每个人都说一种方言,那么就会导致我们听不懂对方的意思,也无法交流。

1.OSI的体系结构
(从高到低)应用层—表示层—会话层—运输层—网络层—数据链路层—物理层
2.TCP/IP的体系结构
应用层——运输层(TCP或UDP)——网际层IP——网络接口层
3.五层协议的体系结构(两个协议的折中结构)
应用层——运输层——网络层——数据链路层——物理层

网络编程的目的:

进行数据交换,信息交流等,完成不同ip地址的主机之间的通信

如果实现网络中的主机之间的相互通信

  1. 进行通信的主机,双方的ip地址和端口号
  2. 网络协议,比如TCP/IP协议

利用ip地址在网络中找到这台主机,然后用端口号找到具体的应用程序

IP


  1. ip地址是Internet上的计算机的唯一标识,也是进行通信的实体,借助ip地址可以唯一定位一台网络上的计算机
  2. 本机localhost是127.0.0.1
  3. IP地址的分类方式为IPV4和IPV6
  4. 通常我们会用域名来取代具体的ip地址,这样方便记忆
    比如在cmd窗口ping www.baidu.com
    在这里插入图片描述
    实际上ping的还是百度的ip地址,但是用域名方便了我们记住
    输入一个主机的域名时,域名服务器(DNS)负责将域名转化成IP地址,从而连接到对应的主机

//InetAddress类 表示Internet协议(IP)地址package TCPDemo;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class InetAddressDemo1 {public static void main(String[] args) {try{//查询本机地址InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");System.out.println(inetAddress1);InetAddress inetAddress2 = InetAddress.getByName("localhost");System.out.println(inetAddress2);InetAddress inetAddress3 = InetAddress.getLocalHost();System.out.println(inetAddress3);//查询网站ip地址InetAddress inetAddress4 = InetAddress.getByName("www.baidu.com");System.out.println(inetAddress4); //www.baidu.com/14.215.177.39//常用方法//获取该网站的ip地址System.out.println(inetAddress4.getHostAddress()); //14.215.177.39//获取该网站的域名System.out.println(inetAddress4.getHostName()); //www.baidu.com}catch(UnknownHostException e){e.printStackTrace();}}
}

结果为
在这里插入图片描述

端口号


  1. 端口号用来标识正在计算机上运行的进程(程序),不同的进程有不同的端口号
  2. 端口是一个 16 位的整数,范围是0~65535
  3. TCP和UDP各有65535个端口号。TCP于UDP可以取一样的端口号,是因为在两个协议下。但是在同一个协议下,端口号不能重复
  4. 端口号的分类
    (1)公认端口 0~1023
    公认端口一般与明确表明了某种服务的协议绑定,如:80端口对应HTTP
    (2)注册端口 1024~49151
    注册端口是用来分配给用户和程序的
    (3)动态 / 私有端口 49152~65535
    理论上,不会给服务提供这些端口

可以通过 netstat -ano 查看所有的端口
可以通过 netstat -ano|findstr “端口号” 查看指定的端口

package TCPDemo;
import java.net.InetSocketAddress;
public class InetSocketAddressDemo1 {public static void main(String[] args) {InetSocketAddress address1 = new InetSocketAddress("127.0.0.1",8080);InetSocketAddress address2 = new InetSocketAddress("localhost",8080);System.out.println(address1); // /127.0.0.1:8080System.out.println(address2); // localhost/127.0.0.1:8080System.out.println(address1.getAddress()); // /127.0.0.1//获取地址System.out.println(address1.getHostName()); // 127.0.0.1//获取端口System.out.println(address1.getPort()); // 8080}
}

TCP与UDP

TCP

  1. 类似于打电话,需要通信双方建立稳定的连接,任何一方掉线都会导致通信的结束
  2. TCP的客户端和服务端有着明确的界限

TCP的服务端和客户端建立连接的过程可以看这篇博客
java通信一:Socket通信原理简单理解

TCP的三次握手(建立连接)

这里用B站up @遇见狂神说的比喻,我觉得很生动形象
A是客户端,B是服务端
A:你瞅啥
B:瞅你咋地
A:打一架
翻译一下也就是
A先跟B沟通,希望建立连接
然后B要回应A,可以建立连接,然后确定A还在不在
A再回应B
这样三次握手,就可以建立连接了

TCP的四次挥手(断开连接)

A:我要断开连接了
B:我知道你要断开了(询问第一遍)
B:你真的要断开吗(再次确认一遍)
A:我真的要断开了

————————

UDP

  1. 类似于发短信,不需要建立稳定的连接,不管对方有没有准备好,都可以直接发给对方
  2. UDP的客户端和服务端没有明确的界限
  3. UDP不用连接,但是需要知道对方的地址

TCP实例


实例一、传输字符串

客户端将字符串hello传入到服务端

package TCPDemo;import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;//客户端
public class TCPClientDemo1 {public static void main(String[] args) {Socket socket = null;try {// 1.要知道服务器的地址,端口号InetAddress serverIP = InetAddress.getByName("127.0.0.1");int port = 9999;// 2.创建一个socket连接socket = new Socket(serverIP,port);// 3.发送消息 用IO流的方式/*客户端上的使用1.getInputStream方法可以得到一个输入流,客户端的Socket对象上的getInputStream方法得到输入流其实就是从服务器端发回的数据。2.getOutputStream方法得到的是一个输出流,客户端的Socket对象上的getOutputStream方法得到的输出流其实就是发送给服务器端的数据。*/OutputStream os = socket.getOutputStream();os.write("hello".getBytes());} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {if(socket!=null){try {socket.close();} catch (IOException e) {e.printStackTrace();}}}}
}

package TCPDemo;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;//服务端
public class TCPServerDemo1 {public static void main(String[] args) {//在这里初始化是为了在finally中关闭资源ServerSocket serverSocket = null;Socket socket = null;InputStream is = null;ByteArrayOutputStream baos = null;try {//1. 服务端首先要有一个地址//这里的端口号是自己编的,ip地址用的本地地址127.0.0.1serverSocket = new ServerSocket(9999);//2. 等待客户端的连接//这里的socket对象和客户端里面的socket对象是一个对象,只不过写到两个类里面//accept()方法是监听客户端连接过来的socket,并返回一个socket//服务端与客户端建立连接,用的是这一个socket连接,所以两个对象相同socket = serverSocket.accept();// 3.读取客户端的消息/*服务器端上的使用1.getInputStream方法得到的是一个输入流,服务端的Socket对象上的getInputStream方法得到的输入流其实就是从客户端发送给服务器端的数据流。2.getOutputStream方法得到的是一个输出流,服务端的Socket对象上的getOutputStream方法得到的输出流其实就是发送给客户端的数据。*/is = socket.getInputStream();//具体读取数据有两种方式//方式一,常规的,只用InputStream/*byte[] buffer = new byte[1024];int len;//将数据读入缓冲区数组buffer中,再将buffer数组转为字符串while((len=is.read(buffer))!=-1){String s = new String(buffer, 0, len);System.out.println(s);}*///方式二,用ByteArrayOutputStream//is.read(buffer)将客户端的数据读入到buffer缓冲数组中//再用ByteArrayOutputStream将buffer数组中的数据写入自己的字节数组缓冲区//这样做的好处是可以避免乱码baos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len;while((len=is.read(buffer))!=-1){baos.write(buffer,0,len);}System.out.println(baos.toString());/*//这样可以一直接收客户端发来的消息while(true){socket = serverSocket.accept();is = socket.getInputStream();baos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len;while((len=is.read(buffer))!=-1){baos.write(buffer,0,len);}System.out.println(baos.toString());}*/} catch (IOException e) {e.printStackTrace();} finally{//关闭资源//注意关闭的顺序if(baos!=null){try {serverSocket.close();} catch (IOException e) {e.printStackTrace();}}if(is!=null){try {is.close();} catch (IOException e) {e.printStackTrace();}}if(socket!=null){try {socket.close();} catch (IOException e) {e.printStackTrace();}}if(serverSocket!=null){try {serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}}
}

运行时,先运行服务端
后运行客户端
最后在服务端的输出窗口看到字符串
在这里插入图片描述
将服务端的代码改成while循环结构,就可以让服务端一直接收客户端发来的消息,客户端运行几次,服务端打印几条消息
在这里插入图片描述

实例二、传输文件

package TCPDemo;/*** 这是客户端的代码,作用是将图片文件picture.jpg传入服务端* 文件传入完毕后,立刻开始接收服务端传来的消息*/import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;public class TCPClientDemo2 {public static void main(String[] args) throws IOException {//1.创建一个Socket链接Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9999);//2.创建一个输出流OutputStream os = new FileOutputStream("picture/picture.jpg");//3.读取文件FileInputStream fis = new FileInputStream("picture/picture.jpg");//4.写出文件byte[] buffer = new byte[1024];int len;while((len=fis.read(buffer))!=-1){os.write(buffer,0,len);}//通知服务器,我已经传输完毕了socket.shutdownOutput();//确定服务器接收完毕,才能断开连接InputStream inputStream = socket.getInputStream();//用ByteArrayOutputStream将inputStream里面的数据写出来//ByteArrayOutputStream里面的缓冲区是字节数组,这样保证不会格式转换错误ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] bytes = new byte[1024];int len1;while((len1=inputStream.read(bytes))!=-1){baos.write(bytes,0,len1);}System.out.println(baos.toString());//5.关闭流baos.close();inputStream.close();fis.close();os.close();socket.close();}
}

package TCPDemo;/*** 这是服务端的代码,作用是接收客户端传来的文件* 然后将文件写入本地文件夹当中* 文件写入完毕后,给客户端发送消息*/import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;public class TCPServerDemo2 {public static void main(String[] args) throws IOException {//1.创建服务ServerSocket serverSocket = new ServerSocket(9999);//2.监听客户端的连接Socket socket = serverSocket.accept();//获取输入流InputStream is = socket.getInputStream();//文件输出FileOutputStream fos = new FileOutputStream(new File("picture/picture1.jpg"));byte[] buffer = new byte[1024];int len;while((len=is.read(buffer))!=-1){fos.write(buffer,0,len);}//通知客户端我接收完毕了OutputStream outputStream = socket.getOutputStream();outputStream.write("ok".getBytes());//关闭资源outputStream.close();fos.close();is.close();socket.close();serverSocket.close();}
}

运行结果
在这里插入图片描述
在这里插入图片描述

UDP实例

package TCPDemo;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;//UDP不需要连接服务器,所以这里也没有区分Client和Server
public class UDPDemo1 {public static void main(String[] args) throws IOException {// 1.建立一个Socket连接//如果这里DatagramSocket socket = new DatagramSocket(8080);//那么UDPDemo2也可以发送包到这个8080端口,然后UDPDemo1也可以接收包//所以说UDP没有明显区分客户端和服务端DatagramSocket socket = new DatagramSocket();// 2. 建立一个包String msg = "hello";//发送给谁InetAddress localhost = InetAddress.getByName("localhost");int port = 9090;// 参数含义:第一个参数是数据,中间两个参数是数据长度的起点与终点,最后两个参数是要发送给谁DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,port);// 3. 发送包socket.send(packet);//这段代码的主体步骤是第一、三步,即建立连接然后发送包//中间的步骤都是在创建包// 4.关闭流socket.close();}
}

package TCPDemo;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;//这里用来接收UDPDemo1 发送的包,但是这里不是服务器
//同样可以用UDPDemo2 来给UDPDemo1 发送包
//UDPDemo2 相当于一直在监听状态,直到UDPDemo1将包发送过来
public class UDPDemo2 {public static void main(String[] args) throws IOException {//开放端口,如果不建立Socket连接,那么UDPDemo1怎么发包都没用,因为没有人接收DatagramSocket socket = new DatagramSocket(9090);//接收数据包byte[] buffer = new byte[1024];DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);socket.receive(packet); //阻塞接收,也就说直到成功接收前,都一直存活//获取发送方的ip地址System.out.println(packet.getAddress().getHostAddress());//输出接收到的包里面的数据System.out.println(new String(packet.getData(),0,packet.getLength()));//关闭连接socket.close();}
}

结果为
在这里插入图片描述


推荐阅读
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
author-avatar
mobiledu2502914667
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有