一、网络编程概述
是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
网络编程就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。
有人说,20世纪最伟大的发明不是计算机,而是计算机网络。还有人说,如果你买了计算机而没有联网,就等于买了电话机而没有接电话线一样。
二、网络模型
计算机网络之间以何种规则进行通信,就是网络模型研究问题。
网络模型一般是指OSI开发参考模型和TCP/IP参考模型。
网络参考模型图
网络模型7层概述:
1.物理层
主要定义物理设备标准,如网线接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由0和1转换为电流强弱来进行传输,到达目的地后再转化为0和1,也就是我们常说的数模转换和模数转换),这一层的数据叫做比特。
2.数据链路层:主要将物理层接收到的数据进行MAC地址(网卡的地址)的封装与接封装。常常把这一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。
3.网络层:主要将下层接收到的数据进行IP地址的封装与接封装。在这一层工作的设备是路由器,常常把这一层的数据叫做数据包。
4.传输层:定义了一些传输数据的协议和端口号等,如TCP协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据;UDP,用于纯属可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的。
5.会话层:通过传输层进行数据传输的通路,主要在系统之间发起会话或者接受会话请求。
6.表达曾:主要是进行对接收的数据进行解释、加密和解密、压缩与解压缩等。
7.应用层:主要是一些中断的引用。如QQ、FTP等。
三、网络编程三要素
IP地址:网络中设备的标识,不易记忆,可用主机名
端口:用于标识进程的逻辑地址,不同进程标识不同
传输协议:TCP、UDP
四、IP地址
要想在网络中的计算机能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接收数据的计算机和识别发送的计算机,在TCP/IP协议中,这个标志号就是IP地址。简而言之,IP地址就是网络中计算机的唯一标识。
计算机只能识别二进制的数据,所以我们的IP地址应该是一个二进制数据,但是,实际上,我们配置的IP地址却不是二进制的数据,why?
例如:IP地址 192.168.1.100
换算 11000000 10101000 00000001 01100100
但是,太长了,所以,为了方便记忆,我们就把IP地址的每一个字节上的数据换算成十进制,然后用.隔开来表示。
IP地址的组成:网络号段+主机号段
A类1.0.0.1---127.255.255.254
B类128.0.0.1---191.255.255.254172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。
C类192.0.0.1---223.255.255.254192.168.X.X是私有地址
D类224.0.0.1---239.255.255.254
E类240.0.0.1---247.255.255.254
(1)10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址)
(2)127.X.X.X是保留地址,用做循环测试用的。
为了方便我们获取和操作IP地址,java提供了InetAddress类供我们使用。
package cn3; import java.net.InetAddress; /** * 如果一个类没有构造方法 * 1.全部成员都是静态的 * 2.单例 * 3.有一个静态的方法,返回此类的实例 * */ public class InetAddressDemo { public static void main(String[] args) throws Exception{ //通过主机名获取一个IP地址对象 InetAddress net = InetAddress.getByName("localhost"); //获取IP地址对象对应的主机名和主机地址 String hostName = net.getHostName(); String address = net.getHostAddress(); //输出IP地址对象对应的主机名和主机地址 System.out.println("主机名:"+hostName+",主机地址:"+address); } }
主机名:localhost,主机地址:127.0.0.1
五、端口号
物理端口 网卡口
逻辑端口 我们平常所说的就是逻辑端口
每个网络程序都会至少有一个逻辑端口。
用于标识进程的逻辑地址,不同进程的标识不同。
有效端口:0-65535,其中0-1024系统使用或保留端口
六、协议
UDP:将数据源和目的封装成数据包中,不需要建立连接;每个数据包的大小限制在64k;因为没有连接,是不可靠协议,不需要建立连接,速度快。
TCP:建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手完成连接;是可靠协议;必须建立连接,所以,效率相对低些。
七、Socket
Socket套接字:网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
Socket原理机制:
通信的两段都有Socket。
网络通信其实就是Socket间的通信。
数据在两个Socket间通过IO传输。
八、UDP发送和接收数据
package cn3; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /* *UDP发送数据 */ public class SendDemo { public static void main(String[] args) throws IOException { //1.创建一个发送数据的UDP对象 DatagramSocket socket = new DatagramSocket(); //发送数据的目的地地址 InetAddress net = InetAddress.getByName("localhost"); //端口号 int port = 10000; //发送的数据 byte[] b = "你好,世界!".getBytes(); //发送数据的长度 int len = b.length; //2.将地址+端口+数据封装到一个数据包中,以便UDP发送对象发送 //从中我们可以看出,UDP是一个不可靠的协议,它将地址+端口+数据封装到一起去发送, //这样接收方拿到数据包,再解析数据包,但是我们不能 保证接收方一定会接收到这个数据包,万一丢失呢 DatagramPacket p = new DatagramPacket(b, len, net,port); //3.发送数据包 socket.send(p); //4.释放资源 socket.close(); } }
package cn3; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; public class GetDemo { public static void main(String[] args) throws IOException { //1.创建一个接受数据的UDP对象 DatagramSocket socket = new DatagramSocket(10000); //2.定义一个数据包用来接收数据 byte[] b = new byte[1024]; int len = b.length; DatagramPacket p = new DatagramPacket(b, len); //3.UDP对象将数据接收并存在在上面定义的数据包中 socket.receive(p); //从数据包中取得数据 byte[] data = p.getData(); int length = p.getLength(); System.out.println(new String(data,0,length)); //4.释放资源 socket.close(); } }
当然,我们必须先启动接收端,让它一直处于等待状态,一旦发送端启动了,那么接收端会理解接收数据包,并解析数据包,然后接收端和发送端都关闭线程。
代码简化
package cn4; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; public class GetDemo { public static void main(String[] args) throws IOException { //传感接收数据的Socket对象 DatagramSocket ds = new DatagramSocket(10087); //创建一个数据包 byte[] b = new byte[1024]; DatagramPacket p = new DatagramPacket(b, b.length); //接收数据 ds.receive(p); //解析数据 String address = p.getAddress().getHostAddress(); String str = new String(p.getData(),0,p.getLength()); System.out.println("从"+address+"获取数据:"+str); //释放资源 ds.close(); } }
package cn4; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class SetDemo { public static void main(String[] args) throws IOException { //创建发送端的Socket对象 DatagramSocket ds = new DatagramSocket(); //创建数据并打包 byte[] b = "你好,世界!".getBytes(); DatagramPacket p = new DatagramPacket(b, b.length,InetAddress.getByName("localhost"),10087); //发送数据包 ds.send(p); //释放资源 ds.close(); } }
九、TCP发送和接收数据
package cn5; /** * TCP协议接收数据 * 1.创建接收端的Socket对象 * 2.监听客户端连接,返回一个对应的Socket对象 * 3.获取输入流,读取数据显示在控制台 * 4.释放资源 * */ import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; public class GetDemo { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(12307); Socket socket = serverSocket.accept(); InputStream inputStream = socket.getInputStream(); byte[] b = new byte[1024]; int len = 0 ; while((len=inputStream.read(b)) != -1){ System.out.println(new String(b,0,len)); } socket.close(); } }
package cn5; import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; /** * TCP发送数据 * 1.创建发送端的Socket对象 * 这一步如果成功,就说明连接已经建立成功了 * 2.获取输出流,写数据 * 3.释放资源 */ public class SendDemo { public static void main(String[] args) throws IOException { //创建发送端的Socket对象 //由此可以看出tcp先要和服务器取得连接,如果发送端先启动,会出现异常 “三次握手” //Exception in thread "main" java.net.ConnectException: Connection refused: connect Socket socket = new Socket(InetAddress.getByName("localhost"),12307); //获取输出流 OutputStream outputStream = socket.getOutputStream(); //写数据 outputStream.write("你好".getBytes()); //释放资源 socket.close(); } }