Java的网络编程

来源:互联网 发布:c 逆波兰算法 编辑:程序博客网 时间:2024/06/14 08:26
网络分层:
为了减少网络设计的复杂性,绝大多数网络采用分层设计方法。所谓分层设计方法,就是按照信息的流动过程将网络的整体功能分解为一个个的功能层,不同机器上的同等功能层之间采用相同的协议,同一机器上的相邻功能层之间通过接口进行信息传递。


计算机网络是指由通信线路相互连接的许多自主工作的计算机构成的集合体,各个部件之间以何种规则进行通信,就是网络模型研究的问题。网络模型一般是指OSI七层参考模型和TCP/IP四层参考模型。这两个模型在网络中应用最为广泛。

开放式系统互连参考模型(Open System Interconnect 简称OSI)是国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定的开放系统互连参考模型,为开放式互连信息系统提供了一种功能结构的框架。它从低到高分别是:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。




TCP/IP是一组用于实现网络互连的通信协议。Internet网络体系结构以TCP/IP为核心。基于TCP/IP的参考模型将协议分成四个层次,它们分别是网络访问层、网际互联层、传输层(主机到主机)和应用层。


1、应用层:
应用层对应于OSI参考模型的高层,为用户提供所需要的各种服务,例如:FTP、Telnet、DNS、SMTP等。


2、传输层:
传输层对应于OSI参考模型的传输层,为应用层实体提供端到端的通信功能,保证了数据包的顺序传送机数据的完整性,该层定义了两个主要协议:
传输控制协议(TCP)和用户数据报协议(UDP)。

TCP协议提供的是一种可靠的,通过“三次握手”来连接的数据传输服务;

而UDP协议提供的则是不保证可靠的(并不是不可靠)、无连接的数据传输服务。


3、网际互联层:

网际互联层对应于OSI参考模型的网络层,主要解决主机到主机的通信问题。它所包含的协议设计数据包在整个网络上的逻辑传输。注重重新赋予主机一个IP地址来完成对主机的寻址,它还负责数据包在多种网络中的路由。

该层有三个主要协议:

网际协议(IP)、互联网组管理协议(IGMP)和互联网控制报文协议(ICMP)。

IP协议是网际互联层最重要的协议,它提供的是一个可靠、无连接的数据报传递服务。

4、网络接入层(即主机-网络层)
网络接入层与OSI参考模型中的物理层和数据链路层相对应。它负责监视数据在主机和网络之间的交换。事实上,TCP/IP本身并未定义该层的协议,而由参与互联的各网络使用自己物理层和数据链路层协议,然后与TCP/IP的网络接入层进行连接。地址解析协议(ARP)工作在此层,即OSI参考模型的数据链路层。



什么是套接字:
源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字。其用于标识客户端请求的服务器和服务。


什么是网络编程:通过使用套接字来达到进程间通信目的编程就是网络编程。

进程之间的通信:
1、在同一台电脑上,A进程和B进程相互通信。
2、在网络中(外网/内网),A电脑中的a程序和B电脑的b程序相互通信(有网络连接)


网络编程三要素:
1.IP地址;
2.端口;
3.协议。数据传递/交互规则


IP:
网络之间互联的协议(IP)是Internet Protocol的外语缩写,中文缩写“网协”:
网络之间互联的协议也就是为计算机网络相互连接进行通信而设计的协议。IP地址具有唯一性。在Java中使用InetAddress类来表示IP地址。

代码获取主机IP:

/** * Created by Layne_Yao on 2017-8-1 下午3:44:44. * CSDN:http://blog.csdn.net/Jsagacity */public class InetAddressDemo {public static void main(String[] args) throws Exception {//static InetAddress getByName(String host) 在给定主机名的情况下确定主机的 IP 地址。 //InetAddress ip = InetAddress.getByName("PC-20170414NJUH");InetAddress ip = InetAddress.getByName("www.baidu.com");System.out.println(ip);//获取主机名称System.out.println(ip.getHostName());//获取主机IPSystem.out.println(ip.getHostAddress());}}

运行结果:



端口:
“端口”是英文port的意译,可以认为是设备与外界通讯交流的出口。端口可分为虚拟端口和物理端口,其中虚拟端口指计算机内部或交换机路由器的端口,不可见。例如计算机中的80端口、21端口等。物理端口又称为接口,计算机背板的RJ45网口(水晶头)、电话RJ11插口也属于物理端口的范畴。


按端口课分为三大类:
1) 公认端口:从0到1023,它们紧密绑定于一些服务。通常这些端口的通讯明确表明某种服务的协议。例如:80端口实际上总是HTTP。
2) 注册端口:从1024到49151.它们松散地绑定于一些服务。也就是有许多服务绑定了这些端口,这些端口同样有许多的其他的目的。例如:许多系统处理动态端口从1024开始。
3) 动态或私有端口:从49152到65535。理论上,不应为服务分配这些端口。四级上机器通常从1024期分配动态端口。但是也有例外:SUN的RPC端口从32768开始。


端口结论:
1) 在同一台电脑中端口不能重复,若重复,则报错端口冲突;
2) 如果我们需要自定义端口号,建议使用10000以上的。


协议:
协议(Protocol),网络协议的简称,网络协议是通信计算机双方必须共同遵从的一组。如怎么建立连接、怎么相互识别等。只有遵守这个约定,计算机之间才能相互通信交流。它的三要素:语法、语义和时序。


网络协议,也可简称协议,通常有三要素组成:
1) 语法:即数据与控制信息的结构或格式;
2) 语义:即需要发出何种控制信息,完成何种动作以及做出何种响应;
3) 时序(同步),即事件实现顺序的详细说明。


http----超文本传输协议资源
https----用安全套接字层的超文本传输协议
ftp----文件传输协议
mailto----电子邮件地址
file----当地电脑或网上分享的文件


物理层:以太网,调制解调器,电力线通信(PLC),SONET/SDH,G.709,光导纤维,同轴电缆,双绞线等;
数据链路层:WIFI,WiMAX,ATM,DTM,令牌环,以太网,FDDI,帧中继,GPRS,EVDO,HSPA,HDLC,PPP,L2TP,PPTP,ISDN,STP等
网络层协议:IP,ICMP,ICMPv6,IGMP,IS-IS,IPsec,ARP,RARP等
传输层协议:TCP,UDP,TLS,DCCP,SCTP,RSVP,OSPF等
应用层协议:DHCP,DNS,FTP,Gopher,HTTP,IMAP4,IPC,NNTP,XMPP,POP3,SIP,SMTP,SNMP,SSH,TELNET,RPC,RTCP,RTP,RTSP,SDP,SOAP,GTP,STUN,NTP,SSDP,BGP,RIP等


URI:统一资源标识符是一个用于标识某一互联网资源名称的字符串。
URL:统一资源定位符是对于可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每一个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。


在Java中,URI表示一个统一资源的标识符,不能用于定位任何资源,唯一作用就是解析。
而URL则包含一个可以打开到达该资源的输入流,可以简单理解URL是URI的特例。

通过URL请求一下百度:返回的只是杂乱的代码,这里没有浏览器进行渲染。

/** * Created by Layne_Yao on 2017-8-1 下午3:54:01. * CSDN:http://blog.csdn.net/Jsagacity */public class URLConnectionDemo {public static void main(String[] args) throws Exception {// https://www.baidu.com/URL url = new URL("https://www.baidu.com/");//打开URL的连接对象URLConnection conn = url.openConnection();//InputStream getInputStream() 返回从此打开的连接读取的输入流//网络-->输入-->程序InputStream in = conn.getInputStream();Scanner sc = new Scanner(in);while(sc.hasNextLine()){String line = sc.nextLine();System.out.println(line);}sc.close();}}

网络编程的编码和解码:

URLEncoder和URLDecoder用于完成普通字符串和application/x-www-form-urlencoded MIME字符串之间的相互转换。

HTML格式编码的实用工具类。该类包含了将String转换为application/x-www-form-urlencoded MIME格式的静态方法。有关HTML格式编码的更多信息,请参阅HTML规范
对String编码时,使用以下规则:
1、字母数字字符“a”到“z”、“A”到“Z”和“0”到“9”保持不变。
2、特殊字符“.”、“-”、“*”和“_”保持不变。
3、空格字符“ ”转换为一个加号“+”。
4、所有其他字符都是不安全的,因此首先使用一些编码机制将它们转换为一个或多个字节。然后每个字节用一个包含三个字符的字符串“%xy”表示,其中xy为该字节的两位十六进制表示形式。推荐的编码机制是UTF-8.但是,出于兼容性考虑,如果未指定一种编码,则使用相应平台的默认编码。

简单的编码解码演示:

public class EncodingDemo {public static void main(String[] args) throws Exception {//获取平台的默认的字符集System.out.println(System.getProperty("file.encoding"));String str = "URLEncoder和URLDecoder完成字符串的编码和解码";//使用UTF-8编码String ret = URLEncoder.encode(str, "UTF-8");System.out.println(ret);//使用UTF-8解码String msg = URLDecoder.decode(ret, "UTF-8");System.out.println(msg);}}

运行结果:


网络编程的编码和解码:
在web的浏览器中,不同的浏览器的编码和解码规则是不一样的。
对于W3C浏览器:遵循W3C组织规范的浏览器(非IE)
编码:byte[] data = "".getByte(String charsetName);
解码:String str = new String(data,String charsetName);
对于IE浏览器:
编码使用的application/x-www-form-urlencoded MIME机制




传输层的协议:
TCP:
面向连接(经历三次握手)、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据(流模式)、速度慢、建立连接需要开销较多(时间、系统资源)。

TCP的传输和接收:(服务器端)

/** * Created by Layne_Yao on 2017-7-29 下午3:35:45. * CSDN:http://blog.csdn.net/Jsagacity */public class Receive {public static void main(String[] args) throws Exception {//创建接收端对象DatagramSocket receiver = new DatagramSocket(10010);byte[] buffer = new byte[1024];//接收数据DatagramPacket dp = new DatagramPacket(buffer,1024);receiver.receive(dp);//获取接收的数据String msg = new String(dp.getData(),0,dp.getLength());System.out.println("发过来的数据:"+msg);}}

客户端:

/** * Created by Layne_Yao on 2017-7-29 下午2:43:26. * CSDN:http://blog.csdn.net/Jsagacity */public class Client {public static void main(String[] args) throws Exception {//创建客户端对象,并指明连接服务端的主机和端口Socket client = new Socket("localhost",10012);//获取客户端的输入流对象Scanner sc = new Scanner(client.getInputStream());while(sc.hasNextLine()){String line = sc.nextLine();System.out.println(line);}sc.close();client.close();}}

先运行服务器端,再运行客户端!!!


UDP:面向非连接、传输不可靠(丢包[数据丢包])、用于传输少量数据(数据包模式)、速度快。

UDP的发送和接收:(服务器端)

/** * Created by Layne_Yao on 2017-7-29 下午2:43:11. * CSDN:http://blog.csdn.net/Jsagacity */public class Server {public static void main(String[] args) throws Exception {String data = "我是服务器,这是服务器传过来的数据!";//创建服务端,指定端口为10000ServerSocket server = new ServerSocket(10012);System.out.println("服务器准备就绪.......");//接收连接该服务端的客户端对象boolean accept = true;while(accept){Socket client = server.accept();System.out.println("连接过来的客户端"+client.getInetAddress());//获取该客户端的输出流对象,给该客户端输出数据PrintStream out = new PrintStream(client.getOutputStream());out.println(data);out.close();}server.close();}}

发送端:

/** * Created by Layne_Yao on 2017-7-29 下午3:35:05. * CSDN:http://blog.csdn.net/Jsagacity */public class Send {public static void main(String[] args) throws Exception {String str = "我是发送端,这是发送端的数据!!!";//创建发送端对象DatagramSocket sender = new DatagramSocket(10011);//发送数据DatagramPacket dp = new DatagramPacket(str.getBytes(),//发送的数据str.getBytes().length,//发送数据的长度(字节数)InetAddress.getLocalHost(),//发送给哪个IP10010);//发送给哪个端口程序sender.send(dp);sender.close();}}

同样的,先运行服务器端,再运行发送端!!!