15Java网络编程.docx
- 文档编号:4332252
- 上传时间:2022-11-29
- 格式:DOCX
- 页数:18
- 大小:251.83KB
15Java网络编程.docx
《15Java网络编程.docx》由会员分享,可在线阅读,更多相关《15Java网络编程.docx(18页珍藏版)》请在冰豆网上搜索。
15Java网络编程
15.1计算机网络基础知识
15.1.1什么是计算机网络
把分布在不同地理区域的计算机与专门的外部设备用通信线程互相连接成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息,共享硬件、软件、数据信息等资源。
计算机网络的主要功能:
资源共享、信息传输与处理、综合服务等。
15.1.2网络通信协议
协议protocol:
通信双方必须遵循的规矩由iso规定
网络通信协议:
网络协议是构成网络的基本组件之一,协议是若干规则和协定的组合。
网络通信协议是分层的:
一般指A机器的第n层与B机器的第n层的对话,这种对话中所使用的若干规则和约束便称为第n层网络协议。
15.1.2.1网络通信分层模型
15.1.2.2网络协议参考模型
osi参考模型7层:
(应-表-会-传-网-数-物)
应用层表示层会话层传输层网络层数据链路层物理层
tcp/ip模型4层:
应用层{http超文本传输协议ftp文件传输协议telnet远程登录ssh安全外壳协议stmp简单邮件发送pop3收邮件}
传输层{tcp传输控制协议udp用户数据包协议}
网络层{ip网际互联协议icmp网络控制消息协议igmp网络组管理协议}
网络接口层{arp地址转换协议,rarp反向地址转换协议,mpls多协议标签交换}
15.1.2.3TCP/IP协议具体说明
TCP/IP协议是一个工业标准协议套件,专为跨广域网(WAN)的大型互联网络而设计。
TCP/IP网络体系结构模型就是遵循TCP/IP协议进行通信的一种分层体系,现今,Internet和Intranet所使用的协议一般都为TCP/IP协议。
在了解该协议之前,我们必须掌握基于该协议的体系结构层次,而TCP/IP体系结构分为四层。
第一层网络接口层
包括用于协作IP数据在已有网络介质上传输的协议,提供TCP/IP协议的数据结构和实际物理硬件之间的接口。
比如地址解析协议(AddressResolutionProtocol,ARP)等。
第二层网络层
对应于OSI模型的网络层,主要包含了IP、RIP等相关协议,负责数据的打包、寻址及路由。
还包括网间控制报文协议(ICMP)来提供网络诊断信息。
第三层传输层
对应于OSI的传输层,提供了两种端到端的通信服务,分别是TCP和UDP协议。
第四层应用层
对应于OSI的应用层、表达层和会话层,提供了网络与应用之间的对话接口。
包含了各种网络应用层协议,比如Http、FTP等应用协议。
TCP/IP体系模型相对于OSI模型的7层结构来说更简单更实用!
现已成为因特网之间的标准协议模型。
常见的应用层协议:
1.超文本传输协议(HTTP):
用于传输组成万维网Web页面的文件,大部分Web项目都是基于该协议实现用户数据的传输。
2.文件传输协议(FTP):
交互式文件传输
3.简单邮件传输协议(SMTP):
用于传输邮件消息和连接
4.终端访问协议(Telnet):
远程登录到网络主机
5.域名系统(DNS)
6.路由选择信息协议(RIP)
15.1.2.4数据封装和解封装过程
15.1.3TCP与UDP
TCP/IP网络体系主要包含两种协议:
TCP、UDP协议。
TCP协议:
传输控制协议面向连接的协议能保证传输安全可靠速度慢(有3次握手)
UDP协议:
用户数据包协议非面向连接速度快不可靠
1、IP协议的最直观认识就是为Internet网络中提供独一无二的IP地址。
IP(InternetProtocol)协议是一种低级路由协议,该协议主要实现将传输数据分解成许多小数据包,接着通过网络将这些数据包传到一个指定地址,但是,请注意,IP协议并不会保证传输的数据包一定到达目的地,或者是数据包的完整性!
2、TCP协议最直观的认识是一定保证正确完整的数据传输。
TCP(ThransferControlProtocol传输控制协议)协议正好弥补了IP协议的不足,属于一种较高级的协议,它实现了数据包的有力捆绑,通过排序和重传来确保数据传输的可靠(即数据的准确传输以及完整性)。
排序可以保证数据的读取是按照正确的格式进行,重传则保证了数据能够准确传送到目的地!
3、UDP协议与TCP协议类似,它们之间的区别在于TCP协议是面向连接的可靠数据传输协议,而UDP协议是面向数据报的不可靠数据传输协议;UDP(UserDatagramProtocol用户数据报协议)协议可以要求数据传输的目的地可以没有连接甚至不存在,数据传输效率更快,但可靠性低,TCP正好相反。
4、注意,TCP与UDP协议均属于传输层协议,而IP协议属于网络层协议。
15.1.3.1TCP与UDP数据包
TCP与UDP数据包(数据帧)的基本格式
协议类型:
TCP、UDP
15.1.3.2协议的选择
(1)对数据可靠性的要求
对数据要求高可靠性的应用需选择TCP协议,如验证、密码字段的传送都是不允许出错的,而对数据的可靠性要求不那么高的应用可选择UDP传送。
(2)应用的实时性
TCP协议在传送过程中要使用三次握手、重传确认等手段来保证数据传输的可靠性。
使用TCP协议会有较大的时延,因此不适合对实时性要求较高的应用,如VOIP、视频监控等。
相反,UDP协议则在这些应用中能发挥很好的作用。
(3)网络的可靠性
由于TCP协议的提出主要是解决网络的可靠性问题,它通过各种机制来减少错误发生的概率。
因此,在网络状况不是很好的情况下需选用TCP协议(如在广域网等情况),但是若在网络状况很好的情况下(如局域网等)就不需要再采用TCP协议,而建议选择UDP协议来减少网络负荷。
15.1.4Socket
Socket是网络驱动层提供给应用程序编程接口和一种机制。
套接口,也叫“套接字”。
是操作系统内核中的一个数据结构,它是网络中的节点进行相互通信的门户。
它是网络进程的ID。
网络通信,归根到底还是进程间的通信(不同计算机上的进程间通信)。
在网络中,每一个节点(计算机或路由)都有一个网络地址,也就是IP地址。
两个进程通信时,首先要确定各自所在的网络节点的网络地址。
但是,网络地址只能确定进程所在的计算机,而一台计算机上很可能同时运行着多个进程,所以仅凭网络地址还不能确定到底是和网络中的哪一个进程进行通信,因此套接口中还需要包括其他的信息,也就是端口号(PORT)。
在一台计算机中,一个端口号一次只能分配给一个进程,也就是说,在一台计算机中,端口号和进程之间是一一对应关系。
所以,使用端口号和网络地址的组合可以唯一的确定整个网络中的一个网络进程。
例如,如网络中某一台计算机的IP为10.92.20.160,操作系统分配给计算机中某一应用程序进程的端口号为1500,则此时10.92.20.1601500就构成了一个套接口。
15.1.5通信端口
每一个应用协议都有其特定的端口,通过端口实现服务器同时能够服务于很多不同的客户端,服务器进程通过监听端口来捕获客户端连接。
一个服务器允许在同个端口接受多个客户,一个服务器也能开启多个端口接受客户请求。
能够接受并管理多个客户连接的服务器进程必须是支持多线程的(或者采用同步输入/输出处理多路复用技术的其它方法)
端口号详解:
1、每一个端口都有特定的端口号,TCP/IP协议中的端口号是一个占2个字节(16位)的数字,它的范围是0~65535。
2、同时该号一般对应一些特定协议,TCP/IP为特定协议保留了低端的1024个端口,其中,端口80是HTTP协议的,21是FTP协议的,23是Telnet协议的等等。
3、客户和服务器必须事先约定所使用的端口,如果系统两部分所使用的端口不一致,那就不能进行通信。
15.1.6IP地址
通常用户在表达IP地址时采用的是点分十进制表示的数值(或者是为冒号分开的十进制Ipv6地址),而在通常使用的socket编程中使用的则是二进制值(网络字节序),这就需要将这两个数值进行转换。
ipv4地址:
32bit,4字节,通常采用点分十进制记法。
例如对于:
10000000000010110000001100011111
点分十进制表示为:
128.11.3.31
ip地址的分类:
特殊的ip地址:
15.2InetAddress类的使用
通常,人们在使用过程中都不愿意记忆冗长的IP地址,尤其到Ipv6时,地址长度多达128位,那时就更加不可能一次性记忆那么长的IP地址了。
因此,使用主机名或域名将会是很好的选择。
主机名与域名的区别:
主机名通常在局域网里面使用,主机名可以解析到对应的ip;域名通常是再internet上使用。
众所周知,XX的域名为:
,而这个域名其实对应了一个XX公司的IP地址,那么XX公司的IP地址是多少呢?
我们可以利用ping来得到XX公司的ip地址,如图:
由此可知,主机名或域名是跟指定的ip地址相关联的。
.InetAddress类是java的IP地址封装类,内部隐藏了IP地址,可以通过它很容易的使用主机名以及IP地址。
一般供各种网络类使用。
直接由Object类派生并实现了序列化接口。
该类用两个字段表示一个地址:
hostName与address。
hostName包含主机名,address包含IP地址。
InetAddress支持ipv4与ipv6地址。
一些常用方法如下:
·staticInetAddressgetLocalHost():
返回本地计算机的InetAddress。
·StringgetHostName():
返回指定InetAddress对象的主机名。
·StringgetHostAddress():
返回指定InetAddress对象的主机地址的字符串形式
·staticInetAddressgetByName(Stringhostname):
使用DNS查找指定主机名或域名为hostname的IP地址,并返回InetAddress。
·byte[]getAddress():
返回指定对象的IP地址的以网络字节为顺序的4个元素的字节数组。
应用举例:
InetAddressaddr=InetAddress.getByName("")
System.out.println(addr);
以上代码将打印网址域名为的对应主机和IP地址信息。
因此,在网络编程中,我们可以很方便的使用InetAddress类实现Ip地址的各种操作。
示例如下:
import.*;
publicclassTestNet{
publicstaticvoidmain(String[]args)throwsException{
//获得本地主机的相关信息
InetAddressia=InetAddress.getLocalHost();
//获取本地ip地址
System.out.println(ia.getHostAddress());
//获取本地主机名
System.out.println(ia.getHostName());
//获得制定域名的主机信息
System.out.println(InetAddress.getByName(""));
}
}
15.3TCP
包中定义了两个类ServerSocket和Socket,分别用来实现双向连接的server端和client端。
15.3.1ServerSocket
ServerSocket被设计成在等待客户建立连接之前不做任何事情的监听器,此时实现服务器套接字。
构造方法如下:
ServerSocket构造函数解读:
如果主机只有一个IP地址,那么默认情况下,服务器程序就与该IP地址绑定。
对于参数backlog,它表示等待队列,是输入连接指示(对连接的请求)的最大队列长度被设置为backlog参数。
如果队列满时收到连接指示,则拒绝该连接。
对这句话的理解是backlog表示的是连接请求的队列长度,而不是请求连接的客户端的数目,所以虽然这里同时建立了几十个client,但是可能client一发出连接请求server马上就接受了,所以是否请求拒绝取决于server处理连接请求的速度。
如果server来不及处理连接请求,才把请求放入队列,一旦请求队列满了,就拒绝。
对于参数bindAddr,它显式指定服务器要绑定的IP地址,该构造方法适用于具有多个IP地址的主机。
例:
假定一个主机有两个网卡,一个网卡用于连接到Internet,IP地址为10.3.129.125,还有一个网卡用于连接到本地局域网,IP地址为192.168.1.1。
如果服务器仅仅被本地局域网中的客户访问,那么可以按如下方式创建ServerSocket:
ServerSocketserverSocket=newServerSocket(8888,10,InetAddress.getByName("192.168.1.1"));
ServerSocket还定义了以下一些常用的方法:
·accept
方法原型:
publicSocketaccept()throwsIOException
方法说明:
该方法用于告诉服务器不停地等待,直到有客户端连接到该ServerSocket指定的端口,一旦有客户端通过网络向该端口发送正确的连接请求,该方法就会返回一个表示服务器与客户端连接已建立的Socket对象,接下来我们就可以通过这个返回的Socket对象实现服务器与指定客户端的通信。
注意:
accept()方法会让服务器中的当前线程暂停下来,直到有客户端的正确连接发送过来。
·bind
方法原型:
publicvoidbind(SocketAddressendpoint)throwsIOException
方法说明:
ServerSocket有一个不带参数的默认构造方法。
通过该方法创建的ServerSocket不与任何端口绑定,接下来还需要通过bind()方法与特定端口绑定。
这个默认构造方法的用途是,允许服务器在绑定到特定端口之前,先设置ServerSocket的一些选项。
因为一旦服务器与特定端口绑定,有些选项就不能再改变了。
在以下代码中,先把ServerSocket的SO_REUSEADDR选项设为true,然后再把它与8000端口绑定:
方法举例:
ServerSocketserverSocket=newServerSocket();
serverSocket.setReuseAddress(true);//设置ServerSocket的选项
serverSocket.bind(newInetSocketAddress(8000));//与8000端口绑定
如果把以上程序代码改为:
ServerSocketserverSocket=newServerSocket(8000);
serverSocket.setReuseAddress(true);//设置ServerSocket的选项
那么serverSocket.setReuseAddress(true)方法就不起任何作用了,因为SO_REUSEADDR选项必须在服务器绑定端口之前设置才有效。
·close
方法原型:
publicvoidclose()throwsIOException
方法说明:
关闭当前ServerSocket。
任何当前被锁定的线程将在accept()方法中抛出IOException。
·getInetAddress
方法原型:
InetAddressgetInetAddress()
方法说明:
返回此服务器套接字的本地地址。
·getLocalPort
方法原型:
intgetLocalPort()
方法说明:
返回此套接字在其上侦听的端口。
另外,从jdk1.4开始,java提供了关于ServerSocket的ServerSocketChannel,jdk建议用管道来实现客户端连接的监听以及关闭服务器套接字会更安全,因此,现在我们应该通过ServerSocket来得到其套接字管道,通过管道来实现服务监听以及关闭,可以通过ServerSocket的getChannel()方法来得到当前ServerSocket的相关管道。
示例如下:
//例一:
服务器端代码TCPServer.java
importjava.io.*;
import.*;
publicclassTCPServer{
publicstaticvoidmain(String[]args)throwsException{
ServerSocketss=newServerSocket(8888);
System.out.println("服务器已准备...");
while(true){
Sockets=ss.accept();
if(s!
=null){
System.out.println("已连接"+s.getLocalAddress().getHostName()+"客户端");
BufferedReaderin=newBufferedReader(newInputStreamReader(s.getInputStream()));
Stringmsg=null;
while((msg=in.readLine())!
=null&&!
msg.trim().equals("EXIT")){
System.out.println(msg);
}
}
}
}
}
通过上面的代码,我们分析得知,套接字只是实现数据传输的接口,真正实现数据传输的是封装在套接字中的输入、输出流。
执行javaTCPServer之后,程序停在原处不动了,这就表示服务器在等待客户端的连接,说明了如果只有一端启动是不能进行通讯的。
程序说明:
该程序为服务器端程序,该程序开启了一个端口号为8888的特定端口,并且开启了服务器套接字在该端口上监听客户请求,accept()方法阻塞当前线程直到有客户端请求发送过来,当请求正确时,该方法将客户端套接字引用传递出来,这样,网络之间的数据发送就好像是本地数据调用。
15.3.2Socket
该类为建立连向服务器套接字及启动协议交换而设计,当进程通过网络进行通信的时候,java技术使用流模型来实现数据的通信。
一个Socket包括两个流,分别为一个输入流和一个输出流,一个进程如果要通过网络向另一个进程发送数据,只需简单地写入与Socket相关联的输出流,同样,一个进程通过从与Socket相关联的输入流来读取另一个进程所写的数据。
如果通过TCP协议建立连接,则服务器必须运行一个单独的进程来等待连接,而某一客户机必须试图到达服务器,就好比某人打电话,必须保证另一方等待电话呼叫,这样才能实现两人之间的通信。
Socket类的构造方法:
Socket():
默认的无参构造方法
Socket(Stringhost,intport):
创建一个流套接字并将其连接到指定主机上的指定端口号
Socket(InetAddressnet,intport):
创建一个流套接字并将其连接到指定IP地址的指定端口号。
Socket类的其他常见方法:
publicOutputStreamgetOutputStream()throwsIOException:
返回此套接字的输出流。
publicInputStreamgetInputStream()throwsIOException:
返回此套接字的输入流。
voidconnect(SocketAddressendpoint):
将此套接字连接到服务器。
publicSocketChannelgetChannel():
返回与此数据报套接字关联的唯一SocketChannel对象(如果有)。
publicvoidclose()throwsIOException:
关闭此套接字。
InetAddressgetLocalAddress():
获取套接字绑定的本地地址。
intgetLocalPort():
返回此套接字绑定到的本地端口。
intgetPort():
返回此套接字连接到的远程端口。
示例如下:
//例二:
客户端代码TCPClient.java
importjava.io.*;
import.*;
publicclassTCPClient{
publicstaticvoidmain(String[]args)throwsException{
Sockets=newSocket("127.0.0.1",8888);//"192.168.0.188"
if(s!
=null){
System.out.println("已连接"+s.getLocalAddress().getHostName()+"服务器端");
BufferedReaderin=newBufferedReader(newInputStreamReader(System.in));
PrintWriterout=null;
Stringmsg=null;
try{
while(!
(msg=in.readLine().trim()).equals("EXIT")){
out=newPrintWriter(newOutputStreamWriter(s.getOutputStream()));
out.println(msg);
out.flush();
}
}finally{
out.println("EXIT");
out.flush();
out.close();
s.close();
}
}
}
}
15.3.3多线程与TCP通信
但你可能会发现,此程序只能允许一个客户端进行操作,即:
其它客户端程序无法再进行Socket连接,那该如何去解决这个问题呢?
应该还记得之前讲解过的多线程的概念,只要在服务器端实现多线程,则服务器可以同时处理多个客户端请求。
示例如下(只需要修改服务器端代码TCPServer.java如下即可):
importjava.io.*;
import.*;
publicclassTCPServerextendsThread{
publicvoidrun(){
try{
ServerSocketss=newServerSocket(8888);
Sockets=null;
System.out.println("服务器已准备...");
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 15 Java 网络 编程
![提示](https://static.bdocx.com/images/bang_tan.gif)