网络通信协议
计算机网络中实现通信必须有一些约定,即通信协议,对速率、传输代码、代码结构、传输控制步骤、出错控制等制定标准。
通信协议分层的思想
由于结点之间联系很复杂,在制定协议时,把复杂成份分解成一些简单的成份,再将它们复合起来。最常用的复合方式是层次方式,即同层间可以通信、上一层可以调用下一层,而与再下一层不发生关系。各层互不影响,利于系统的开发和扩展。的
七层协议
应用层协议:与其它计算机进行通讯的一个应用,它是对应应用程序的通信服务的。例如,一个没有通信功能的字处理程序就不能执行通信的代码,从事字处理工作的程序员也不关心OSI的第7层。但是,如果添加了一个传输文件的选项,那么字处理器的程序员就需要实现OSI的第7层。示例:DHCP ·DNS · FTP · Gopher · HTTP· IMAP4 · IRC · NNTP · XMPP ·POP3 · SIP · SMTP ·SNMP · SSH ·TELNET · RPC · RTCP · RTP RTSP· SDP · SOAP · GTP · STUN · NTP· SSDP · BGP · RIP 等
表示层协议:这一层的主要功能是定义数据格式及加密。例如,FTP允许你选择以二进制或ASCII格式传输。如果选择二进制,那么发送方和接收方不改变文件的内容。如果选择ASCII格式,发送方将把文本从发送方的字符集转换成标准的ASCII后发送数据。在接收方将标准的ASCII转换成接收方计算机的字符集。示例:加密,ASCII等。
会话层协议:它定义了如何开始、控制和结束一个会话,包括对多个双向消息的控制和管理,以便在只完成连续消息的一部分时可以通知应用,从而使表示层看到的数据是连续的,在某些情况下,如果表示层收到了所有的数据,则用数据代表表示层。示例:RPC,SQL等。
传输层协议:这层的功能包括是否选择差错恢复协议还是无差错恢复协议,及在同一主机上对不同应用的数据流的输入进行复用,还包括对收到的顺序不对的数据包的重新排序功能。示例:TCP · UDP · TLS · DCCP · SCTP · RSVP · OSPF 等
网络层协议:这层对端到端的包传输进行定义,它定义了能够标识所有结点的逻辑地址,还定义了路由实现的方式和学习的方式。为了适应最大传输单元长度小于包长度的传输介质,网络层还定义了如何将一个包分解成更小的包的分段方法。示例:IP (IPv4 · IPv6) · ICMP· ICMPv6·IGMP ·IS-IS · IPsec · ARP · RARP等
数据链路层协议:它定义了在单个链路上如何传输数据。这些协议与被讨论的各种介质有关。示例:Wi-Fi(IEEE 802.11) · WiMAX(IEEE 802.16) ·ATM · DTM · 令牌环 · 以太网 ·FDDI · 帧中继 · GPRS · EVDO ·HSPA · HDLC · PPP · L2TP · PPTP · ISDN·STP 等
物理层协议:OSI的物理层规范是有关传输介质的特性标准,这些规范通常也参考了其他组织制定的标准。连接头、帧、帧的使用、电流、编码及光调制等都属于各种物理层规范中的内容。物理层常用多个规范完成对所有细节的定义。示例:以太网 · 调制解调器 · 电力线通信(PLC) · SONET/SDH · G.709 · 光导纤维 · 同轴电缆 · 双绞线等
网络编程概述
Java是 Internet 上的语言,它从语言级上提供了对网络应用程序的支持,程序员能够很容易开发常见的网络应用程序。
Java提供的网络类库,可以实现无痛的网络连接,联网的底层细节被隐藏在 Java 的本机安装系统里,由 JVM 进行控制。并且 Java 实现了一个跨平台的网络库,程序员面对的是一个统一的网络编程环境。
计算机网络
把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息、共享硬件、软件、数据信息等资源。
网络编程的目的:
直接或间接地通过网络协议与其它计算机进行通讯。
传网络编程中有两个主要的问题
①如何准确地定位网络上一台或多台主机
Internet上的主机有两种方式表示地址:
a. 域名(hostName) www.atguigu.com
b. IP地址(hostAddress) 192.168.10.165
用于表示IP地址的类: InetAddress
InetAddress inet = InetAddress.getByName("www.baidu.com");
String hostName = inet.getHostName();
String hostAddress = inet.getHostAddress();
②找到主机后如何可靠高效地进行数据传输。
若需要安全可靠的完成网络通信需要满足一定的规则,即网络通信协议(TCP、UDP)
InetAddress类主要表示IP地址,两个子类:Inet4Address、Inet6Address。
InetAddress 类对象含有一个 Internet 主机地址的域名和IP地址:www.baidu.com 和 61.135.169.125。
public static void main(String[] args) throws Exception {
// 通过主机名称获取IP地址
InetAddress inet = InetAddress.getByName("www.baidu.com");
// 获取此IP地址的主机域名
String hostName = inet.getHostName();
// 返回IP地址的字符串(以文本表现形式)
String hostAddress = inet.getHostAddress();
System.out.println("主机名称:" + hostName + "\t主机IP地址:" + hostAddress); //输出结果:主机名称:www.baidu.com 主机IP地址:61.135.169.125
// 获取本地主机InetAddress实例
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost); //NewNet-PC/192.168.0.101
}
域名容易记忆,当在连接网络时输入一个主机的域名后,域名服务器(DNS)负责将域名转化成IP地址,这样才能和主机建立连接。 -------域名解析
先找本机hosts(C:\Windows\System32\drivers\etc\hosts ),是否有输入的域名地址,没有的话,再通过DNS服务器,找主机。
传输层协议中有两个非常重要的协议
① 传输控制协议TCP(Transmission Control Protocol)
TCP协议:
①使用TCP协议前,须先建立TCP连接,形成传输数据通道
②传输前,采用“三次握手”方式,是可靠的
③TCP协议进行通信的两个应用进程:客户端、服务端
④在连接中可进行大数据量的传输
⑤传输完毕,需释放已建立的连接,效率低
②用户数据报协议UDP(User Datagram Protocol)
UDP协议:
①将数据、源、目的封装成数据包,不需要建立连接
②每个数据报的大小限制在64K内
③因无需连接,故是不可靠的
④发送数据结束时无需释放资源,速度快
基于TCP协议的网络编程
①利用套接字(Socket)开发网络应用程序早已被广泛的采用,以至于成为事实上的标准。
②通信的两端都要有Socket,是两台机器间通信的端点
③网络通信其实就是Socket间的通信。
④Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
⑤一般主动发起通信的应用程序属客户端,等待通信请求的为服务端
一个IP地址和端口号的组合 称为“套接字” Socket :客户端 ServerSocket:服务端
发送端与接收端:Socket & ServerSocket
客户端发送内容到服务端,服务端接受并给予反馈
//客户端
public void client() throws UnknownHostException, IOException {
//1.通过ip和端口号创建客户端套接字
Socket s = new Socket(InetAddress.getByName("192.168.0.101"), 6868);
//2.发送内容到服务端
FileInputStream fis = new FileInputStream("E:/important/1.jpg");
OutputStream os = s.getOutputStream();
byte[] b = new byte[1024];
int len = 0;
while ((len = fis.read(b)) != -1) {
os.write(b, 0, len);
}
s.shutdownOutput();
//3.接受服务端的反馈
InputStream is = s.getInputStream();
byte[] b1 = new byte[1024];
int len1 = 0;
while ((len1 = is.read(b1)) != -1) {
System.out.println(new String(b1, 0, len1));
}
//4.关闭流和套接字
is.close();
os.close();
fis.close();
s.close();
}
//服务端
public void server() throws IOException {
//1.创建服务端
ServerSocket ss = new ServerSocket(6868);
//2.服务端接受客户端发送的数据
Socket s = ss.accept();
InputStream is = s.getInputStream();
FileOutputStream fos = new FileOutputStream("E:/important/2.jpg");
byte[] b = new byte[1024];
int len = 0;
while ((len = is.read(b)) != -1) {
fos.write(b, 0, len);
}
s.shutdownInput();
//3.服务端给客户端反馈
OutputStream os = s.getOutputStream();
os.write("接受成功".getBytes());
//4.关闭流以及套接字
os.close();
fos.close();
is.close();
s.close();
ss.close();
}
基于UDP协议的网络编程
①类 DatagramSocket 和 DatagramPacket 实现了基于 UDP 协议网络程序。
② UDP数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
③DatagramPacket 对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。
④UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接
发送端与接收端: DatagramSocket & DatagramPacket
发送端发送内容到服务端,接收端接受数据 基于UDP的传输 不需要接收端反馈 发送端只管发 接收端只管接受 一般用于视频(流畅性最主要)
//发送端
public void send() throws IOException {
String str = "使用UDP协议发送数据给接收端!";
//创建套接字
DatagramSocket ds = new DatagramSocket();
byte[] buf = str.getBytes();
int i = 0;
while (i < 100) {
//数据包 每个数据报不能超过 64kb
DatagramPacket dp = new DatagramPacket(buf, 0, buf.length, InetAddress.getByName("127.0.0.1"), 6868);
//使用套接字发送数据包
ds.send(dp);
System.out.println("发送端发送了" + i++ + "个数据");
}
ds.close();
}
//接收端
public void receive() throws IOException, InterruptedException {
//创建套接字
DatagramSocket ds = new DatagramSocket(6868);
byte[] buf = new byte[1024];
int i = 0;
while (i < 100) {
Thread.sleep(50);
//数据包
DatagramPacket dp = new DatagramPacket(buf, buf.length);
//用套接字接受收举报 存储到数据包dp中
ds.receive(dp);
//接受到的数据的字节数组
byte[] data = dp.getData();
System.out.println(new String(data, 0, dp.getLength()));
System.out.println("接收端接收了" + i++ + "个数据");
}
ds.close();
}
public class TcpServer {
private static boolean flag = true; // 服务器开启标志
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(8888);
while (flag) {
// 当服务端程序运行到该阶段时线程阻塞,直到接受客户端请求才向下流转
Socket socket = serverSocket.accept();
new ServerService(socket).run();
}
serverSocket.close();
}
}
class ServerService implements Runnable {
private Socket socket = null;
public ServerService(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
InputStream is = null;
StringBuilder s = new StringBuilder();
// DataInputStream dis = null;
try {
is = socket.getInputStream();
// dis= new DataInputStream(is);
System.out.println("客户端ip地址是:" + socket.getInetAddress());
System.out.println("客户端端口号是:" + socket.getPort());
System.out.println("本地端口号是:" + socket.getLocalPort());
byte buf[] = new byte[1024];
int len = 0;
while ((len = (is.read(buf))) > 0) {
s.append(new String(buf, 0, len));
}
// System.out.println("客户端请求内容:" + dis.readUTF());
System.out.println("客户端请求内容:" + s.toString());
DataOutputStream dout = new DataOutputStream(
socket.getOutputStream());
dout.writeUTF("已收到你发来的消息!!");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// if (dis != null) {
// dis.close();
// }
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}