网络通信
网络程序设计是编写与其他计算机进行通讯的程序。Java已经将网络程序所需要的对象封装成不同的类。只要创建这些类的对,使用相应的方法,即使设计人员不具有关的网络知识,也可以编写处高质量的网络通讯程序
现实两台计算机的通信,必须要用一个网络线路连接两台计算机
服务器<----->网络<------>客户机
服务器:提供信息的计算机或程序
客户机:请求信息的计算机程序
网络:用于连接服务器与客户机
局域网与因特网
1.局域网(Local Area Newwork,LAN)
多个计算机相互连接组成的封闭式计算机组,可以有两台计算机组成;也可以由同以区域内上千台计算机组成
2.因特网(Internet)
由于LAN延伸到更大的范围,这样的网络称为广域网(Wide Area Network,WAN),它主要讲分布在不同地区的局域网或计算机系统互连起来,到达资源共享的目的
因特网(Internet),就是世界范围内最大的广域网
网络协议
网络协议规定了计算机之间连接物理、机械(网线与网卡的连接规定)、电气(有效的电平范围)等待征以及计算机之间的相互寻址规则、数据发送冲突的解决、长的数据如何分段传送与接收等。就像不同的国家有不同的法律一样,目前网络协议有多种
1.IP协议(Internet Protocol)
一种网络协议。Internet网络采用的协议是TCP/IP协议,其全称是Transmission Control Protocol/Internet Protocol。Internet网络上存在数以亿计的主机,每一台主机在网络上用为其分配的Internet地址代表自己,这个地址就是IP地址
IPv4:到目前为止IP地址用4个字节,也就是32位的二进制数来表示,称为IPv4。为了便于使用,通常取用每个字节的十进制数,并且每字节之间用圆点隔开表示IP地址,如127.0.0.1
IPv6:使用16个字节来表示IP地址
TCP/IP模式是一种层次结构,共分为4层,分别为应用层、传输层、网络互连层和主机到网络层。各层实现特定的功能,提供特定的服务个访问接口,并具有相对的独立性
2.TCP/UDP协议
在TCP/IP协议栈中,有两个高级协议是网络应用程序编写者一个了解的,即TCP(Transmission Control Protococl,传输控制协议)与UDP(User Datagram Protocol,用户数据报协议)
TCP协议(固连接,传输靠谱)
TCP协议是一种以固连接线为基础的协议,它是提供两台计算机间可靠的数据传送。TCP可以保证从一端数据送至连接的另一端时,数据能够确实送达,而且抵达的数据的排列顺序和送出时的顺序相同,因此,TCP协议适合可靠性要求比较高的场合。就想拨打电话,必须先拨号给对方,等待两端确定连接后,相互才能听到对方说话,也知道对方回应的是什么
HTTP、FTP和Telnet等都需要使用可靠的通信频道,例如,HTTP从某个URL读取数据时,如果收到的数据顺序与发送时不相同,就可能会出现一个混乱的HTML文件或是一些无效的信息
UDP协议(无连接,传输不靠谱)
UDP是无连接通信协议,不保证可靠数据的传输,但能够向若干个目标发送数据,接收发自若干个源的数据。UDP是以独立发送数据包的方式进行。这种方式就像邮递员送信这收信人
UDP协议适合于一些对数据准确性要求不高的场合,如网络聊天室、在线影片等。这是由于TCP协议在认证上存在额外耗费,可能使传输速度减慢,而UDP协议可能会更适合这些对传输速度和时效要求非常高的网站,即使有一小部分数据包遗失或传输顺序有所不同,也不会严重危害该项通信
端口和套接字
1.端口(port)
“端口”是英文port的意译,可以认为是设备与外界通信交流的出口,所有的数据都通过该出口与其他计算机或者设备相连。网络程序设计中的端口并非真实的物理存在,而是一个假想的连接装置。端口被规定为一个在0~65535之间的整数。
HTTP服务一般使用80端口,FTP服务使用21端口。假如一台计算机提供了HTTP、FTP等多种服务,那么客户机会通过不同的端口来确定连接到服务器的哪项服务上
通常0~1023之间的端口用于一些知名的网络服务和应用,用户的普通网络应用应该使用1024以上的端口数,以避免端口号与另一个应用或系统服务所用端口冲突
2.套接字(Socket)
网络程序中的套接字(Socket)用于将应用程序与端口连接起来。套接字是一个假想的连接装置,就像插插头的设备“插座”用于连接电器与电线一样。Java将套接字抽象化为类,程序设计者只需要创建Socket类对象,即可使用套接字
IP地址封装(封装类InetAddress)
IP地址是每台计算机在网络上的唯一标识,它是32位或128位的无符号数字,使用4组数字表示一个固定的编号,如‘192.168.128.255’就是局域网络中的编号
IP地址是一种底级协议,UDP和TCP都是在它的基础上构建的
Java提供了IP地址的封装类InetAddress,它位于java.net包中,主要封装了IP地址,并提供了相关的常用方法,如获取IP地址、主机地址等
InetAddress类的常用方法
方法 | 返回值 | 功能 |
---|---|---|
getByName(String host) | InetAddress | 获取与Host相对应的InetAddress对象 |
getHostAddress() | String | 获取InetAddress对象所含的IP地址 |
getHostName() | String | 获取此IP地址的主机名 |
getLocalHost() | InetAddress | 返回本地主机的InetAddress对象 |
isReachable(int timeout) | boolean | 在timeout指定的毫秒时间内,测试是否可以达到该地址 |
TCP程序设计
TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。在Java中,TCP程序设计是指利用ServerSocket类和Socket类编写的网络通信程序。利用TCP协议进行通信的两个应用程序是由主次之分的,一个称为服务器端程序,另一个称为客户端程序,两者的功能编写方法不大一样
①服务器程序创建一个ServerSocket(服务器端套接字),调用accept()方法等待客户机来连接
②客户端程序创建一个Socket,请求与服务器建立连接
③服务器接收客户机的连接请求,同时创建一个新的Socket与客户建立连接。服务器继续等待新的请求
ServerSocket服务器端
它可以通过指定的端口来等待连接的套接字。服务器套接字一次可以与一个套接字连接。如果多台客户机同时提出连接请求,服务器套接字会将请求连接的客户机存入队列中,然后从中取出一个套接字,与服务器新建的套接字连接起来。若请求连接数大于最大容纳数,则多出的连接请求被拒绝。队列的默认大小是50
ServerSocket类的构造方法
ServerSocket类的构造方法都抛出IOException异常
构造方法 | 描述 |
---|---|
ServerSocket() | 创建非绑定服务器套接字 |
ServerSocket(int port) | 创建绑定到特定端口的服务器套接字 |
ServerSocket(int port,int backlog) | 利用指定的backlog创建服务器套接字并将其绑定到指定的本地端口号 |
ServerSocket(int port,int backlog,InetAddress bindAddress) | 使用指定端口、侦听bcklog和要绑定到本地IP地址创建服务器 |
这种情况适用于计算机上有多块网卡和多个IP地址的情况,用于可以明确规定ServerSocket在哪块网卡或IP地址上对待你客户的连接请求 |
ServerSocket类的常用方法
方法 | 返回值 | 描述 |
---|---|---|
accept() | Socket | 等待客户机的连接。若连接,则创建一个套接字 |
isBound() | boolean | 判断ServerSocket的绑定状态 |
getInetAddress() | InetAddress | 返回此服务器套接字的本地地址 |
isClosed() | boolean | 返回服务器套接字的关闭状态 |
close() | void | 关闭服务器套接字 |
bind(SocketAddress endpoint) | void | 将ServerSocket绑定到特定地址(IP地址和端口号) |
getLocalPort() | int | 返回服务器套接字等待的端口号 |
使用ServerSocket对象的accept()方法时,会阻塞线程的继续执行,直到接收到客户端的呼叫。
Socket客户端
调用ServerSocket类的accept()方法会返回一个和客户端Socket对象相连接的Socket对象,java.net包中的Socket类用于表示客户端套接字,它采用TCP建立计算机之间的连接,并包含了Java语言所有对TCP有关的操作方法,如建立连接、传输数据、断开连接等。
Socket构造方法
Socket类定义了多个构造方法,它们可以根据InetAddress对象或者字符串指定的IP地址和端口号创建实例。
构造方法 | 描述 |
---|---|
Socket() | 通过系统默认类型的SocketImpl创建为连接套接字 |
Socket(InetAddress address,int port) | 创建一个流套接字并将其连接到指定IP地址的指定端口号 |
Socket(InetAddress address,int port,InetAddress localAddr,int localPort) | 创建一个套接字并将其连接到指定远程地址上的指定远程端口 |
Socket(String host,int port) | 创建一个流套接字并将其连接到指定主机上的指定端口号 |
Socket(String host,int port,InetAddress localAddr,int localPort) | 创建一个套接字并将其连接到指定远程主机上的指定远程端口 |
Socket类常用方法
方法 | 返回值 | 描述 |
---|---|---|
bind(SocketAddress bindpoint) | void | 将套接字绑定到本地地址 |
close() | void | 关闭此套接字 |
connect(SocketAddress endpoint) | void | 将此套接字连接到服务器 |
connect(SocketAddress endpoint,int timeout) | void | 将此套接字连接到服务器,并指定一个超时值 |
getInetAddress() | InetAddress | 返回套接字连接的地址 |
getInputStream() | InputStream | 返回此套接字的输入流 |
getLocalAddress() | InetAddress | 获取套接字绑定的本地地址 |
getLocalPort() | int | 返回此套接字绑定到的本地端口 |
getOutputStream() | OutputStream | 返回此套接字的输出流 |
getPort() | int | 返回此套接字连接到的远程端口 |
isBound() | boolean | 返回此套接字的绑定状态 |
isClosed() | boolean | 返回套接字的关闭状态 |
isConnected() | boolean | 返回套接字的连接状态 |
TCP网络程序实例
(1)服务器端
创建服务器端类Server,首先创建服务器端套接字对象;然后监听客户接入,并读取接入的客户端IP地址和传入得消息;最后像接入的客户端发送一条信息
(2)客户端
创建客户端类Client,在程序中,首先创建客户端套接字,连接指定的服务器;然后向服务器端发送数据和接收服务器端传输的数据
UDP程序设计
UDP(User Datagram Protocol,用户数据报协议),它是网络信息传输的另一种形式。UDP通信和TCP通信不同,基于UDP的信息传递更快,但不提供可靠的保证,虽然UDP是一种不可靠的协议,但如果需要较快地传输信息,并能够容忍小的错误,可以考虑使用UDP
基本模式:
(1)将数据打包(称为数据包),然后将数据包发往目的地
(2)接收别人发来的数据包,然后查看数据包
使用Java进行UDP程序设计
1.发送数据包
(1)使用DatagramSocket()创建一个数据包套接字
(2)使用DatagramPackage(byte[] buf,int offset,int length,InetAddress address,int port):创建要发送的数据包
2.接收数据包
(1)使用DatagramSocket(int port)创建数据包套接字,绑定到指定的端口
(2)使用DatagramPacket(byte[] buf,int length)创建字节数组来接收数据包
(3)使用DatagramPacket类的receive()方法接收UDP包
DatagramPacket类
java.net包的DatagramPacket类用来表示数据包,该类的构造方法函数如下。
(1)DatagramPacket(byte[] buf,int length):创建DatagramPacket对象,指定了数据包的内存空间和大小
(2)DatagramPacket(byte[] buf,int length,InetAddress address,int port):创建DatagramPacket对象,不仅指定了数据包的内存空间和大小,还指定了数据包的目标地址和端口
在发送数据时,必须指定接收方的Socket地址和端口,因此使用第二种构造函数可以创建发送数据的DatagramPacket对象
DatagramPacket类的常用方法
方法 | 返回值 | 描述 |
---|---|---|
getAddress() | InetAddress | 返回某台机器的IP地址,此数据报将要发往该机器或者是从该机器接收到的 |
getData() | byte[] | 返回数据缓冲区 |
getLength() | int | 返回将要发送或接收到的数据的长度 |
getOffset() | int | 返回将要发送或接收到的数据偏移量 |
getPort() | int | 返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的 |
getSocketAddress() | SocketAddress | 获取要将此包发送到的或者发出此数据报的远程主机的SocketAddress |
setAddress(InetAddress iaddr) | void | 设置要将此数据报发往的那台机器的IP地址 |
setData(byte[] buf)、setData(byte[] buf,int offset,int length) | void 为此包设置数据缓冲区 | |
setLength(int length) | void | 设置要将此数据报发往的远程主机上的端口号 |
setSocketAddress(SocketAddress address) | void | 设置要将此数据报发往的远程主机的SocketAddress(通常为IP地址+端口号) |
DatagramSocket类
java.net包中的DatagramSocket类用于表示发送和接收数据包的套接字,该类的构造方法函数有以下3种
(1)DatagramSocket():创建DatagramSocket对象,构造数据报套接字并将其绑定到本机主机上任何可用的端口
(2)DatagramSocket(int port):创建DatagramSocket对象,创建数据报套接字并将其绑定到本地主机上的指定端口
DatagramSocket(int port,InetAddress addr):创建DatagramSocket对象,创建数据报套接字,并将其绑定到指定的本地地址,该构造函数适用于有多块网卡和多个IP地址的情况
DatagramSocket类的常用方法
方法 | 返回值 | 描述 |
---|---|---|
bind(SocketAddress addr) | void | 将此DatagramSocket绑定到特定的地址和端口 |
close() | void | 关闭此数据报套接字 |
connect ( InetAddress address,int port) | void | 将套接字连接到此套接字的远程地址 |
coonect(SocketAddress addr) | void | 将此套接字连接到远程套接字地址(IP地址+端口号) |
disconnect() | void | 断开套接字的连接 |
getInetAddress() | InetAddress | 返回此套接字连接的地址 |
getLocalAddress() | InetAddress | 获取套接字绑定的本地地址 |
getLocalPort() | int | 返回此套接字绑定的本地主机上的端口号 |
getLocalSocketAddress() | SocketAddress | 返回此套接字绑定的端点的地址,如果尚未绑定则返回null |
getPort() | int | 返回此套接字的绑定状态 |
isBound() | boolean | 返回套接字的绑定状态 |
isClosed() | boolean | 返回是否关闭了套接字 |
isConnected() | boolean | 返回套接字的连接状态 |
receive(DatagramPacket p) | void | 从此套接字接收数据包 |
send(DatagramPacket p) | void | 从此套接字发送数据包 |
使用DatagramSocket类创建的套接字是单个的数据报套接字。UDP协议是一种多播数据传输协议,那么可以创建多播的数据报套接字吗?答案是肯定的,DatagramSocket类提供了一个子类MulticatSocket,它表示多播数据报套接字,该类用于发送个接收IP多播包。MulticastSocket类是IP地址范围在224.0.0.0和239.255.255.255的范围内(包括两者),但这里需要说明的是地址224.0.0.0虽然被保留,但不一个使用
由于MulticastSocket类是DatagramSocket类的子类,因此他包含DatagramSocket类中的所有公有方法,除此之外,它还有两个特殊的方法joinGroup和leaveGroup
(1)joinGroup(InetAddress mcastaddr):加入多播组,参数mcastaddr表示要加入的多播地址
(2)leaveGroup(InetAddress mcastaddr):离开多播组,参数mcastaddr表示要离开的多