计算机网络是通过传输介质、通信设施和网络通信协议,把分散在不同地点的计算机设备互连起来,实现资源共享和数据传输的系统。网络编程就就是编写程序使联网的两个(或多个)设备(例如计算机)之间进行数据传输。Java语言对网络编程提供了良好的支持,通过其提供的接口我们可以很方便地进行网络编程。下面先对网络编程的一些基础知识进行介绍,最后给出使用Java语言进行网络编程的实例。
网络中每台计算机的唯一标识,通过ip地址可以找到指定的计算机
用户标识进程的逻辑地址,通过端口可以找到指定进程。有效端口为0-65535,其中0-1024端口为系统端口,一般不能被使用。
协议是定义的通信规则。
TCP协议:是在通信的两台设备之间建立连接通道,对传输的数据大小没有限制,但是因为建立连接,可靠一些,但是速度会慢一些。TCP协议又称为三次握手协议,因为建立过程有三步,发送请求、获取反馈、建立连接。通常使用的蓝牙、打电话都是TCP协议。
UDP协议:需要将数据打包,因为包有大小,所以对数据大小有限制,UDP是不用建立连接的,不保证待接收方一定会接收到消息,所以不可靠,但是因为不建立连接,速度要快一些。
还有其他的Http/Https/ip等协议。
物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。
数据链路层:主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装。常把这一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。
网络层:主要将从下层接收到的数据进行IP地址(例192.168.0.1)的封装与解封装。在这一层工作的设备是路由器,常把这一层的数据叫做数据包。
传输层:定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。 主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把这一层数据叫做段。
会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)
表示层:主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够能识别的东西(如图片、声音等)。
应用层:主要是一些终端的应用,比如说FTP(各种文件下载),WEB(IE浏览),QQ之类的(可以把它理解成我们在电脑屏幕上可以看到的东西.就是终端应用)。
上面所讲到的ISO/OSI七层模型目前只是一个模型,在实际的网络传输中其实并不是这样使用的,实际的网络传输中使用的其实是TCP/IP四层模型。分别是网络接口层、网际互联层、传输层、应用层。
网络接口层:对应物理层、数据链路层
负责监视数据在主机和网络之间的交换。事实上,TCP/IP本身并没有定义该层的协议,而由参与互连的各个网络使用自己的物理层和数据链路层协议,然后与TCP/IP的网络接入层进行链接
地址解析协议(ARP)工作在此层,即OSI参考模型的数据链路层:ARP就是将IP地址翻译成mac 地址,因为在整个互联网内传输需要IP 地址,但是在同一个网段之内(局域网)传输数据就不是使用IP 地址,而是需要使用mac 地址。
例如,在同一个局域网内传输数据,电脑点击发送数据,而发送的目标是我同局域网内的另一台计算机,点击之后数据就会发送到网线上,网线就会把你的请求发送到交换机上,交换机只能识别mac 地址,不认识IP地址
注意,局域网内部使用交换机,而在局域网之间的连接是通过路由器(路由器是用来进行跨网络通信的,在同一个网络内通信只需要交换机即可)
所以还是需要再学习交换机、路由器等网络设备及其作用、原理
网际互联层:对应网络层
主要解决主机到主机的通信问题。它所包含的协议设计数据包在整个网络上的逻辑传输。
该层有三个主要协议:网际协议(IP)、互联网组管理协议(IGMP)、互联网控制报文协议(ICMP)
传输层:对应传输层
为应用层实体提供端到端的通信功能,保证了数据包的顺序传送及数据的完整性。
该层定义了两个主要的协议:传输控制协议(TCP)、用户数据报协议(UDP)。QQ传输使用的就是UDP协议
还需要深入学习,比如TCP/IP三次握手(为什么要三次握手,搜索“什么是两军问题”,其实三次握手也不能达到绝对可靠,但是相对来说三次已经相当可靠了,如果再握手更多次就太费时间了,太少的话就不能保证足够可靠)
应用层:对应会话层、表示层、应用层
为用户提供所需要的各种服务
例如:FTP、Telnet、DNS、SMTP等
package socket.udp.send;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class Send {
public static void main(String[] args) throws IOException {
//1、创建对象
DatagramSocket ds = new DatagramSocket(10004) ;
//2、声明数据
String str = "hello udp";
/* 发送的字节数 发送的字节数组的长度 发送的主机 发送的端口
* DatagramPacket(byte[] buf, int length, InetAddress address, int port)
构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
*/
DatagramPacket dp = new DatagramPacket(str.getBytes(),
str.getBytes().length,InetAddress.getLocalHost(),10003);
//发送数据
ds.send(dp);
byte[] buf = new byte[1024];
DatagramPacket dp1 = new DatagramPacket(buf,buf.length);
//2、准备接受数据
ds.receive(dp1);
buf = dp1.getData();//获取数据
int len = dp1.getLength();
String ip = dp1.getAddress().getHostAddress();
int port = dp1.getPort();
System.out.println(ip+",端口是:"+port+",发送数据:"+new String(buf,0,len));
}
}
package socket.udp.rec;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class Rec {
public static void main(String[] args) throws IOException {
//1、创建对象
DatagramSocket ds = new DatagramSocket(10003) ;
//构建接收的数据包
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
//2、准备接受数据
ds.receive(dp);
buf = dp.getData();//获取数据
int len = dp.getLength();
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
System.out.println(ip+",端口是:"+port+",发送数据:"+new String(buf,0,len));
//2、声明数据
String str = "hello 个铲铲。。。";
/* 发送的字节数 发送的字节数组的长度 发送的主机 发送的端口
* DatagramPacket(byte[] buf, int length, InetAddress address, int port)
构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
*/
DatagramPacket dp1 = new DatagramPacket(str.getBytes(),
str.getBytes().length,InetAddress.getLocalHost(),10004);
//发送数据
ds.send(dp1);
}
}
分别编写客户端和服务器,分为如下几个个步骤。
客户端 服务器
1.创建套接字(客户端的Socket对象) 1.创建套接字(服务器的Sokcet对象)
2.声明输出数据 2.接受客户端对象
3.分析数据 3.获取客户端的流对象
4.关闭 4.读取数据
5.打印数据
6.关闭