Java从入门到实战总结-3.5、Java网络编程
文章目录
1、网络简述
以下内容主要来自维基百科:https://zh.wikipedia.org/wiki/Wikipedia:%E9%A6%96%E9%A1%B5
(1)、什么是计算机网络
计算机网络(英语:computer network),通常也简称网络,是指容许节点分享资源的数字电信网络
。在电脑网络,电脑设备会透过节点之间的连接(数据链路)互相交换数据。传输介质可分为有线及无线两类
——有线的可用到双绞线、光纤电缆等介质;无线则可用到Wi-Fi、NFC。
用于创建、路由及终止数据传输的电脑网络设备即为网络节点
。节点包括像个人电脑、电话、服务器般的主机及其他网络硬件(如网关及路由器)。它们一般以网络地址作标识符。当一个设备能够与另一设备交换信息时,便可视它们俩已连接成网络,不论它们是否直连。专用通信协议在大多数分层中位于其他更通用的通信协议之上。要维持网络的可靠性,便需要有一定的网络管理技能。
电脑网络为海量应用程序及服务背后的基础
。比如访问互联网、数字视频、数字音频;共享打印机;收发电子邮件及即时通信消息
。电脑网络可依照传输介质、传输协议、 网络大小、拓扑、流量控制机制、创建目的等因素区分。世界上最大的电脑网络为互联网
。
(2)、什么是计算机的IP地址
IP地址
:IP地址(英语:IP Address,全称Internet Protocol Address),又译为网际协议地址、互联网协议地址
。当设备连接网络,设备将被分配一个IP地址,用作标识
。通过IP地址,设备间可以互相通讯
,如果没有IP地址,我们将无法知道哪个设备是发送方,无法知道哪个是接收方。IP地址有两个主要功能:标识设备或网络 和 寻址(英语:location addressing)
。
常见的IP地址分为 IPv4 与 IPv6 两大类
,IP地址由一串数字组成
。IPv4 由十进制数字组成,并以点分隔,如:172.16.254.1; IPv6 由十六进制数字组成,以冒号分割,如:2001:db8:0🔢0:567:8:1。
IP地址有两个主要的功能:
标识主机
:更具体地说,标识其网络接口,并且提供主机在网络中的位置。网络寻址
:网际协议(缩写:IP)的一个重要机制就是网络寻址(英语:internet address)。该功能的目的是将 数据报 从一个网络模块 送到 目的地。在发送的整个过程,IP地址(address)充当着目的地的位置,域名(name)意味着我们要找什么,路由(route)代表着如何到达目的地的这个过程。每个IP数据包的标头包含了发送主机的IP地址和目的主机的IP地址。
IPV4地址由32位二进制数组成,为便于使用,常以XXX.XXX.XXX.XXX形式表现,每组XXX代表小于或等于255的10进制数,该表示方法称为点分十进制。例如维基媒体的一个IP地址是208.80.152.2。地址可分为A、B、C、D、E五大类,其中E类属于特殊保留地址。
IP地址是唯一的。目前IPv4技术可能使用的IP地址最多可有4,294,967,296个(即2^32)。看上去像是很难会用尽,但由于早期编码和分配上的问题,很多区域的编码实际上被空出或不能使用。加上互联网的普及,使大部分家庭都至少有一部电脑,连同公司的电脑,以及连接网络的各种设备都消耗大量IPv4地址资源。
随着互联网的快速成长,IPv4的42亿个地址最终于2011年2月3日用尽。相应的科研组织已研究出128位的IPv6,其IP地址数量最高可达3.402823669 × 10^38个,届时每个人家居中的每件电器,每件对象,甚至地球上每一粒沙子都可以拥有自己的IP地址。
(3)、什么是网络中网站的域名
网域名称
(英语:Domain Name,简称:Domain),简称域名、网域
,是由一串用点分隔的字符组成的互联网上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位。域名可以说是一个IP地址的代称,目的是为了便于记忆后者
。例如,wikipedia.org是一个域名。人们可以直接访问wikipedia.org来代替IP地址,然后域名系统(DNS)就会将它转化成便于机器识别的IP地址。这样,人们只需要记忆wikipedia.org这一串带有特殊含义的字符,而不需要记忆没有含义的数字。
域名的核心是域名系统
(英语:Domain Name System,缩写:DNS),域名系统中的任何名称都是域名。在域名系统的层次结构中,各种域名都隶属于域名系统根域的下级。域名的第一级是顶级域,它包括通用顶级域,例如.com、.net和.org;以及国家和地区顶级域,例如.us、.cn和.tk。顶级域名下一层是二级域名,一级一级地往下。现在,还有一些新兴的中文域名,例如.在线等。这些域名向人们提供注册服务,人们可以用它创建公开的互联网资源或运行网站。顶级域名的管理服务由对应的域名注册管理机构(域名注册局)负责,注册服务通常由域名注册商负责。
截止2019年,已有超过7.41亿个域名被登记注册。
IP地址是因特网主机的作为路由寻址用的数字体标识,不容易记忆,因而产生了域名这一种字符型标识,它比IP地址更容易记忆
。这也是域名的一个重要功能——为数字化的互联网资源提供易于记忆的名称。
另外,域名具有唯一性,在资源更改IP地址时,只需要进行新IP地址与恒定域名的转换,即可实现将资源移动到网络地址拓扑中的不同物理位置
。基于以上两个特性,域名还用于创建个体的唯一标识。任何组织和个人在提供因特网资源时,都可以选择与其名称对应的域名,让其他人轻松访问这些资源。
(4)、什么是计算机的端口号
端口(英语:port),又称为连接端口、端口、协议端口(protocol port)在电脑网络中是一种经由软件创建的服务,在一个电脑操作系统中扮演通信的端点(endpoint)
。每个端口都会与主机的IP地址及通信协议关联。端口以16比特数字来表示,这被称为端口编号(port number)。
位于传输层的通信协议通常需要指定端口号,例如在TCP/IP协议族之下的TCP与UDP协议
。在应用层中,使用主从式架构的通信协议,在每个端口上提供多路复用服务(multiplexing service)。经由公认端口号(well-known port numbers),通常可以辨认出这个连线使用的通信协议,其中具代表性的是最基础的1024个公认端口号(well-known port numbers),例如Telnet协议默认使用23端口来连线,Secure Shell协议默认使用22端口,HTTP协议默认使用80端口,HTTPS协议默认使用443端口。
传输层协议,如传输控制协议(TCP)与用户资料包协议(UDP),在分组表头中,定义了来源端口号与目的端口号。一个端口号使用16位无符号整数(unsigned integer)来表示,其范围介于0与65535之间。在TCP协议中,端口号0是被保留的,不可使用。1–1023 系统保留,只能由root用户使用。1024—4999 由客户端程序自由分配。5000—65535 由服务器端程序自由分配在UDP协议中,来源端口号是可以选择要不要填上,如果设为0,则代表没有来源端口号。
在操作系统中,一个行程可以通过网络套接字将它的输入与输出与一个特定的传输协议、一个端口、一个IP地址关系起来。这个关系动作,称为綁定(binding),在这之后,就可以通过网络提交与接收资料。
在操作系统上运行的网络软件,可以透过操作系统,利用各个不同的端口,将资料发送到网络上;操作系统也可以根据数据包的IP地址以及端口号,将这些数据包转送到符合的行程去。
虽然使用同样传输协议,但是特定的IP地址以及端口的组合,只会被綁定到单一的特定行程上。当使用同样协议的多个程序,尝试着綁定在同一个IP地址下的相同端口,就会产生一个常见的应用程序错误,这个错误有时候被称为端口冲突(port conflicts)。
(5)、什么是计算机之间的通信协议
https://zh.wikipedia.org/wiki/%E7%BD%91%E7%BB%9C%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE
通信协议(英语:Communications Protocol,也称传输协议)在电信领域中指的是,在任何物理介质中允许两个或多个在传输系统中的终端之间传播信息的系统标准,也是指计算机通信或网络设备的共同语言。
通信协议定义了通信中的语法学、语义学和同步规则以及可能存在的错误检测与纠正。通信协议在硬件、软件或两者之间皆可实现。
为了交换大量信息,通信系统使用通用格式(协议)。每条信息都有明确的意义使得预定位置给予响应,并独立实施回应指定的行为,通信协议须参与实体都同意才能生效。为了达成一致,协议必须要有技术标准。编程语言在计算方面也应有相应标准,所以在这个方面可以用编程语言做类比: “编程语言是为了模式化的计算而传输协议为了更畅通的交流”。
多类别协议构建了单个传输的不同方面,包括同时进行的协议模块,和在软件上实现时的协议栈。
网络传输协议(Internet communication protocol)是互联网工程任务组 (IETF)制定的。电气电子工程师学会(IEEE)负责有线无线传输, 国际标准化组织 (ISO) 负责其他类别。ITU-T 负责电信通讯传输以及公共交换电话网 (PSTN)的格式。 在公共交换电话网与网络技术融合的今天,形势驱使着通信标准进一步的合并收敛。
通讯协议又称通信规程,是指通信双方对数据传送控制的一种约定
。约定中包括对数据格式
,同步方式
,传送速度
,传送步骤
,检纠错方式
以及控制字符定义等问题
做出统一规定,通信双方必须共同遵守,它也叫做链路控制规程。
以下为各种网络传输协议列表(后面数字表示应用层协议默认服务端口):
- A:
ARP(地址解析协议) - B:
BGP
BOOTP
Bonjour - C:
CAN(CANbus) - D:
DHCP(动态主机设置协议)
DNS:
DVMRP(Distance-Vector Multicast Routing Protocol)
DDNS - E:
EGP(Exterior Gateway Protocol) - F:
FTP(文件传输协议)
FTPS - G:
GIT
Gopher - H:
HDLC
HELLO
HTTP
HTTPS - I:
ICMP
IDRP(InterDomain Routing Protocol)
IEEE 802
IGMP
IGP(内部网关协议/Interior Gateway Protocol)
IMAP
IP
IPX
IS-IS - L:
LCP(链路控制协议/Link Control Protocol)
LLC(逻辑链路控制协议/Logical Link Control) - M:
MLD(多播监听发现协议/Multicast Listener Discovery) - N:
NCP(网络控制协议/Network Control Protocol)
NNTP
NTP - P:
PPP(点对点协议)
POP(邮局协议) - R:
RARP
RIP(路由信息协议)
RTP
RTSP(即时流协议)
RSVP - S:
SLIP(串行链路连接协议/Serial Link Internet Protocol)
SNMP(简单网络管理协议)
SMTP
SIP
SOCKS
SPDY - T:
TCP(传输控制协议)
TFTP(小型文件传输协议/Trivial File Transfer Protocol)
Telnet - U:
UDP(用户数据报协议) - X:
X.25 - Y:
Yahoo!奇摩即时通 通信协议
(6)、OSI网络模型
开放式系统互联模型(英语:Open System Interconnection Model,缩写:OSI;简称为OSI模型)是一种概念模型,由国际标准化组织提出,一个试图使各种计算机在世界范围内互连为网络的标准框架
。定义于ISO/IEC 7498-1。
该模型将通信系统中的数据流划分为七个层,从跨通信介质传输位的物理实现到分布式应用程序数据的最高层表示。每个中间层为其上一层提供功能,其自身功能则由其下一层提供。功能的类别通过标准的通信协议在软件中实现。
根据建议X.200,OSI将计算机网络体系结构划分为以下七层,标有1~7,第1层在底部。 现“OSI/RM”是英文“Open Systems Interconnection Reference Model”的缩写。
-
第7层 应用层
主条目:应用层
应用层(Application Layer)提供为应用软件而设计的接口,以设置与另一应用软件之间的通信。例如:HTTP、HTTPS、FTP、Telnet、SSH、SMTP、POP3等。 -
第6层 表示层
主条目:表示层
表示层(Presentation Layer)把数据转换为能与接收者的系统格式兼容并适合传输的格式。 -
第5层 会话层
主条目:会话层
会话层(Session Layer)负责在数据传输中设置和维护计算机网络中两台计算机之间的通信连接。 -
第4层 传输层
主条目:传输层
传输层(Transport Layer)把传输表头(TH)加至数据以形成数据包。传输表头包含了所使用的协议等发送信息。例如:传输控制协议(TCP)等。 -
第3层 网络层
主条目:网络层
网络层(Network Layer)决定数据的路径选择和转寄,将网络表头(NH)加至数据包,以形成分组。网络表头包含了网络资料。例如:互联网协议(IP)等。 -
第2层 数据链路层
主条目:数据链路层
数据链路层(Data Link Layer)负责网络寻址、错误侦测和改错。当表头和表尾被加至数据包时,会形成信息框(Data Frame)。数据链表头(DLH)是包含了物理地址和错误侦测及改错的方法。数据链表尾(DLT)是一串指示数据包末端的字符串。例如以太网、无线局域网(Wi-Fi)和通用分组无线服务(GPRS)等。
分为两个子层:逻辑链路控制(logical link control,LLC)子层和介质访问控制(Media access control,MAC)子层。 -
第1层 物理层
主条目:物理层
物理层(Physical Layer)在局部局域网上发送数据帧(Data Frame),它负责管理电脑通信设备和网络媒体之间的互通。包括了针脚、电压、线缆规范、集线器、中继器、网卡、主机接口卡等。
(7)、TCP/IP
互联网协议套件(英语:Internet Protocol Suite,缩写IPS)是网络通信模型,以及整个网络传输协议家族,为网际网络的基础通信架构。它常通称为TCP/IP协议族(英语:TCP/IP Protocol Suite,或TCP/IP Protocols),简称TCP/IP。因为该协议家族的两个核心协议:TCP(传输控制协议)和IP(网际协议),为该家族中最早通过的标准。由于在网络通讯协议普遍采用分层的结构,当多个层次的协议共同工作时,类似计算机科学中的堆栈,因此又称为TCP/IP协议栈(英语:TCP/IP Protocol Stack)。这些协议最早发源于美国国防部(缩写为DoD)的ARPA网项目,因此也称作DoD模型(DoD Model)。这个协议族由互联网工程任务组负责维护。
TCP/IP提供了点对点链接的机制,将资料应该如何封装、寻址、传输、路由以及在目的地如何接收,都加以标准化。它将软件通信过程抽象化为四个抽象层,采取协议堆栈的方式,分别实现出不同通信协议。协议族下的各种协议,依其功能不同,分别归属到这四个层次结构之中,常视为是简化的七层OSI模型。
通常人们认为OSI模型的最上面三层(应用层、表示层和会话层)在TCP/IP组中是一个应用层。由于TCP/IP有一个相对较弱的会话层,由TCP和RTP下的打开和关闭连接组成,并且在TCP和UDP下的各种应用提供不同的端口号,这些功能能够由单个的应用程序(或者那些应用程序所使用的库)增加。与此相似的是,IP是按照将它下面的网络当作一个黑盒子的思想设计的,这样在讨论TCP/IP的时候就可以把它当作一个独立的层。
(8)、TCP/UDP简述
- TCP:
传输控制协议(英语:Transmission Control Protocol,缩写:TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义
。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能。
应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分割成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元(MTU)的限制)。之后TCP把结果包传给IP层,由它来透过网络将包传送给接收端实体的TCP层。TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认信息(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失并进行重传。TCP用一个校验和函数来检验数据是否有错误,在发送和接收时都要计算校验和。
三次握手协议的过程
:
客户端(通过执行connect函数)向服务器端发送一个SYN包,请求一个主动打开。该包携带客户端为这个连接请求而设定的随机数A作为消息序列号。
服务器端收到一个合法的SYN包后,把该包放入SYN队列中;回送一个SYN/ACK。ACK的确认码应为A+1,SYN/ACK包本身携带一个随机产生的序号B。
客户端收到SYN/ACK包后,发送一个ACK包,该包的序号被设定为A+1,而ACK的确认码则为B+1。然后客户端的connect函数成功返回。当服务器端收到这个ACK包的时候,把请求帧从SYN队列中移出,放至ACCEPT队列中;这时accept函数如果处于阻塞状态,可以被唤醒,从ACCEPT队列中取出ACK包,重新创建一个新的用于双向通信的sockfd,并返回。
三次握手和四次挥手简述:三次握手可以简单理解为客户端发送连接请求、服务器响应连接请求、客户端发送确认信息并与服务端建立双向连接;四次挥手可以简单理解为客户端发送断开连接请求、服务端进行断连接确认、客户端确认断开连接、服务端断开和客户端连接。
- UDP:
用户数据报协议(英语:User Datagram Protocol,缩写:UDP;又称用户数据包协议)是一个简单的面向数据报的通信协议,位于OSI模型的传输层
。该协议由David P. Reed在1980年设计且在RFC 768中被规范。典型网络上的众多使用UDP协议的关键应用在一定程度上是相似的。
在TCP/IP模型中,UDP为网络层以上和应用层以下提供了一个简单的接口。UDP只提供数据的不可靠传递,它一旦把应用程序发给网络层的数据发送出去,就不保留数据备份(所以UDP有时候也被认为是不可靠的数据报协议)。UDP在IP数据报的头部仅仅加入了复用和数据校验字段。
UDP适用于不需要或在程序中执行错误检查和纠正的应用,它避免了协议栈中此类处理的开销。对时间有较高要求的应用程序通常使用UDP,因为丢弃数据包比等待或重传导致延迟更可取。
(9)、网络编程程序分类
- B/S程序:浏览器/服务器程序
- C/S程序:客户端/服务器程序
2、TCP/socket网络编程
(1)、ServerSocket
public class ServerSocket
extends Object
implements Closeable
该类实现服务器套接字。 服务器套接字等待通过网络进入的请求。 它根据该请求执行某些操作,然后可能将结果返回给请求者。
服务器套接字的实际工作由SocketImpl类的实例执行。 应用程序可以更改创建套接字实现的套接字工厂,以配置自身以创建适合本地防火墙的套接字。
从以下版本开始:
1.0
- 构造方法:
构造器 | 描述 |
---|---|
ServerSocket() | 创建未绑定的服务器套接字。 |
ServerSocket(int port) | 创建绑定到指定端口的服务器套接字。 |
ServerSocket(int port, int backlog) | 创建服务器套接字并使用指定的待办事项将其绑定到指定的本地端口号。 |
ServerSocket(int port, int backlog, InetAddress bindAddr) | 创建具有指定端口的服务器,监听backlog和要绑定的本地IP地址。 |
- 所有方法
变量和类型 | 方法 | 描述 |
---|---|---|
Socket | accept() | 侦听对此套接字的连接并接受它。 |
void | bind(SocketAddress endpoint) | 将 ServerSocket绑定到特定地址(IP地址和端口号)。 |
void | bind(SocketAddress endpoint, int backlog) | 将ServerSocket绑定到特定地址(IP地址和端口号)。 |
void | close() | 关闭此套接字。 |
ServerSocketChannel | getChannel() | 返回与此套接字关联的唯一ServerSocketChannel对象(如果有)。 |
InetAddress | getInetAddress() | 返回此服务器套接字的本地地址。 |
int | getLocalPort() | 返回此套接字正在侦听的端口号。 |
SocketAddress | getLocalSocketAddress() | 返回此套接字绑定的端点的地址。 |
T | getOption(SocketOption name) | 返回套接字选项的值。 |
int | getReceiveBufferSize() | 获取此 ServerSocket的 SO_RCVBUF选项的值,即建议的缓冲区大小,将用于从 ServerSocket接受的套接字。 |
boolean | getReuseAddress() | 测试是否启用了 SO_REUSEADDR 。 |
int | getSoTimeout() | 检索SO_TIMEOUT的设置。 0返回意味着该选项被禁用(即无穷大的超时)。 |
protected | void implAccept(Socket s) | ServerSocket的子类使用此方法覆盖accept()以返回其自己的套接字子类。 |
boolean | isBound() | 返回ServerSocket的绑定状态。 |
boolean | isClosed() | 返回ServerSocket的关闭状态。 |
ServerSocket | setOption(SocketOption name, T value) | 设置套接字选项的值。 |
void | setPerformancePreferences(int connectionTime, int latency, int bandwidth) | 设置此ServerSocket的性能首选项。 |
void | setReceiveBufferSize(int size) | 设置为默认建议值 SO_RCVBUF选项从该接受的套接字 ServerSocket 。 |
void | setReuseAddress(boolean on) | 启用/禁用 SO_REUSEADDR套接字选项。 |
static void | setSocketFactory(SocketImplFactory fac) | 设置应用程序的服务器套接字实现工厂。 |
void | setSoTimeout(int timeout) | 使用指定的超时启用/禁用 SO_TIMEOUT ,以毫秒为单位。 |
Set<SocketOption<?>> | supportedOptions() | 返回此服务器套接字支持的一组套接字选项。 |
String | toString() | 以 String返回此套接字的实现地址和实现端口。 |
(2)、Socket
public class Socket
extends Object
implements Closeable
该类实现客户端套接字(也称为“套接字”)。 套接字是两台机器之间通信的端点。
套接字的实际工作由SocketImpl类的实例执行。 通过更改创建套接字实现的套接字工厂,应用程序可以将自身配置为创建适合本地防火墙的套接字。
从以下版本开始:
1.0
- 构造方法:
变量 | 构造器 | 描述 |
---|---|---|
Socket() | 创建一个未连接的套接字,系统默认类型为SocketImpl。 | |
Socket(String host, int port) | 创建流套接字并将其连接到指定主机上的指定端口号。 | |
Socket(String host, int port, boolean stream) | 已过时。使用DatagramSocket代替UDP传输。 | |
Socket(String host, int port, InetAddress localAddr, int localPort) | 创建套接字并将其连接到指定远程端口上的指定远程主机。 | |
Socket(InetAddress address, int port) | 创建流套接字并将其连接到指定IP地址处的指定端口号。 | |
Socket(InetAddress host, int port, boolean stream) | 已过时。使用DatagramSocket代替UDP传输。 | |
Socket(InetAddress address, int port, InetAddress localAddr, int localPort) | 创建套接字并将其连接到指定远程端口上的指定远程地址。 | |
Socket(Proxy proxy) | 创建一个未连接的套接字,指定应该使用的代理类型(如果有),而不管其他任何设置。 | |
protected | Socket(SocketImpl impl) | 使用用户指定的SocketImpl创建未连接的Socket。 |
- 所有方法:
变量和类型 | 方法 | 描述 |
---|---|---|
void | bind(SocketAddress bindpoint) | 将套接字绑定到本地地址。 |
void | close() | 关闭此套接字。 |
void | connect(SocketAddress endpoint) | 将此套接字连接到服务器。 |
void | connect(SocketAddress endpoint, int timeout | 使用指定的超时值将此套接字连接到服务器。 |
SocketChannel | getChannel() | 返回与此套接字关联的唯一SocketChannel对象(如果有)。 |
InetAddress | getInetAddress() | 返回套接字连接的地址。 |
InputStream | getInputStream() | 返回此套接字的输入流。 |
boolean | getKeepAlive() | 测试是否启用了 SO_KEEPALIVE 。 |
InetAddress | getLocalAddress() | 获取套接字绑定的本地地址。 |
int | getLocalPort() | 返回此套接字绑定的本地端口号。 |
SocketAddress | getLocalSocketAddress() | 返回此套接字绑定的端点的地址。 |
boolean | getOOBInline() | 测试是否启用了 SO_OOBINLINE。 |
T | getOption(SocketOption name) | 返回套接字选项的值。 |
OutputStream | getOutputStream() | 返回此套接字的输出流。 |
int | getPort() | 返回此套接字连接的远程端口号。 |
int | getReceiveBufferSize() | 获取此 Socket的 SO_RCVBUF选项的值,该值是平台在此 Socket上用于输入的缓冲区大小。 |
SocketAddress | getRemoteSocketAddress() | 返回此套接字连接到的端点的地址,如果未连接则返回 null |
boolean | getReuseAddress() | 测试是否启用了 SO_REUSEADDR 。 |
int | getSendBufferSize() | 获取此 Socket的 SO_SNDBUF选项的值,即此平台在此 Socket上用于输出的缓冲区大小。 |
int | getSoLinger() | 返回 SO_LINGER的设置。 |
int | getSoTimeout() | 返回SO_TIMEOUT的设置。 0返回意味着该选项被禁用(即无穷大的超时)。 |
boolean | getTcpNoDelay() | 测试是否启用了 TCP_NODELAY 。 |
int | getTrafficClass() | 获取从此Socket发送的数据包的IP头中的流量类或服务类型 |
boolean | isBound() | 返回套接字的绑定状态。 |
boolean | isClosed() | 返回套接字的关闭状态。 |
boolean | isConnected() | 返回套接字的连接状态。 |
boolean | isInputShutdown() | 返回套接字连接的读半部分是否已关闭。 |
boolean | isOutputShutdown() | 返回套接字连接的写半部分是否已关闭。 |
void | sendUrgentData(int data) | 在套接字上发送一个字节的紧急数据。 |
void | setKeepAlive(boolean on) | 启用/禁用 SO_KEEPALIVE 。 |
void | setOOBInline(boolean on) | 启用/禁用 SO_OOBINLINE (接收TCP紧急数据)默认情况下,此选项被禁用,并且套接字上收到的TCP紧急数据将被静默丢弃。 |
Socket | setOption(SocketOption name, T value) | 设置套接字选项的值。 |
void | setPerformancePreferences(int connectionTime, int latency, int bandwidth) | 设置此套接字的性能首选项。 |
void | setReceiveBufferSize(int size) | 设置 SO_RCVBUF选项,此规定值 Socket 。 |
void | setReuseAddress(boolean on) | 启用/禁用 SO_REUSEADDR套接字选项。 |
void | setSendBufferSize(int size) | 设置 SO_SNDBUF选项,此规定值 Socket 。 |
static void | setSocketImplFactory(SocketImplFactory fac) | 设置应用程序的客户端套接字实现工厂。 |
void | setSoLinger(boolean on, int linger) | 使用指定的延迟时间(以秒为单位)启用/禁用 SO_LINGER 。 |
void | setSoTimeout(int timeout) | 使用指定的超时启用/禁用 SO_TIMEOUT ,以毫秒为单位。 |
void | setTcpNoDelay(boolean on) | 启用/禁用 TCP_NODELAY (禁用/启用Nagle的算法)。 |
void | setTrafficClass(int tc) | 为从此Socket发送的数据包的IP标头设置流量类或服务类型八位字节。 |
void | shutdownInput() | 将此套接字的输入流放在“流结束”。 |
void | shutdownOutput() | 禁用此套接字的输出流。 |
Set<SocketOption<?>> | supportedOptions() | 返回此套接字支持的一组套接字选项。 |
String | toString() | 将此套接字转换为 String 。 |
(3)、示例
服务端程序:
package com.xiaoyaoyou.day12;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerSocketTest {
/**
* TCP协议网络编程
* 服务器
* @param args
*/
public static void main(String[] args) throws IOException {
//搭建服务器
ServerSocket serverSocket = new ServerSocket(5555);
System.out.println("服务器socket创建成功");
//等待客户端的连接
Socket socket = serverSocket.accept();
System.out.println("一个客户端连接了");
OutputStream outputStream = socket.getOutputStream();
PrintStream printStream = new PrintStream(outputStream);
printStream.println("hello client");
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String text = bufferedReader.readLine();
System.out.println("服务端收到信息:"+text);
System.out.println("服务器程序执行结束");
}
}
客户端程序:
package com.xiaoyaoyou.day12;
import java.io.*;
import java.net.Socket;
public class SocketTest {
/**
* TCP网络编程
* 客户端
* @param args
*/
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 5555);
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String text = bufferedReader.readLine();
System.out.println("客户端收到消息:"+text);
OutputStream outputStream = socket.getOutputStream();
PrintStream printStream = new PrintStream(outputStream);
printStream.println("hello server");
}
}
先运行服务端,再运行客户端:
结果:
服务器socket创建成功
一个客户端连接了
服务端收到信息:hello server
服务器程序执行结束
-------------------------
客户端收到消息:hello client
3、服务器中加入多线程
为了实现服务端支撑多个客户端连接,我们使用多线程处理多个客户端连接,服务端主进程等待客户端连接,一个连接上之后对每个客户端的处理单独创建线程处理:
package com.xiaoyaoyou.day12;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerSocketTest {
/**
* TCP协议网络编程
* 服务器
* @param args
*/
public static void main(String[] args) throws IOException {
//搭建服务器
ServerSocket serverSocket = new ServerSocket(5555);
System.out.println("服务器socket创建成功");
while(true) {
//等待客户端的连接
Socket socket = serverSocket.accept();
System.out.println("一个客户端连接了");
new Thread() {
@Override
public void run() {
OutputStream outputStream = null;
try {
outputStream = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
PrintStream printStream = new PrintStream(outputStream);
printStream.println("hello client");
InputStream inputStream = null;
try {
inputStream = socket.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String text = null;
try {
text = bufferedReader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("服务端收到信息:" + text);
}
}.start();
}
}
}
多个客户端进行消息发送并等待接收服务器消息:
服务器socket创建成功
一个客户端连接了
服务端收到信息:hello server
一个客户端连接了
服务端收到信息:hello server
一个客户端连接了
服务端收到信息:hello server
......
4、相关类和api
(1)、InetAddress
InetAddress类提供了将主机名解析为其IP地址的方法,反之亦然。
InetAddress缓存
InetAddress类具有用于存储成功和不成功主机名解析的缓存。
默认情况下,安装安全管理器时,为了防止DNS欺骗攻击,可以永久缓存正主机名解析的结果。 未安装安全管理器时,默认行为是缓存有限(依赖于实现)时间段的条目。 主机名解析失败的结果将在非常短的时间(10秒)内缓存,以提高性能。
如果不需要默认行为,则可以将Java安全属性设置为正缓存的不同生存时间(TTL)值。 同样,系统管理员可以在需要时配置不同的负缓存TTL值。
两个Java安全属性控制用于正面和负面主机名解析缓存的TTL值:
networkaddress.cache.ttl
表示从名称服务成功进行名称查找的缓存策略。 该值指定为整数,以指示缓存成功查找的秒数。 默认设置是缓存特定于实现的时间段。
值-1表示“永远缓存”。
networkaddress.cache.negative.ttl (默认值:10)
表示名称服务中未成功的名称查找的缓存策略。 该值指定为整数,以指示缓存未成功查找失败的秒数。
值为0表示“从不缓存”。 值-1表示“永远缓存”。
变量和类型 | 方法 | 描述 |
---|---|---|
boolean | equals(Object obj) | 将此对象与指定的对象进行比较。 |
byte[] | getAddress() | 返回此 InetAddress对象的原始IP地址。 |
static InetAddress[] | getAllByName(String host) | 根据主机的名称,根据系统上配置的名称服务返回其IP地址数组。 |
static InetAddress | getByAddress(byte[] addr) | 给定原始IP地址返回 InetAddress对象。 |
static InetAddress | getByAddress(String host, byte[] addr) | 根据提供的主机名和IP地址创建InetAddress。 |
static InetAddress | getByName(String host) | 根据主机名称确定主机的IP地址。 |
String | getCanonicalHostName() | 获取此IP地址的完全限定域名。 |
String | getHostAddress() | 返回文本表示中的IP地址字符串。 |
String | getHostName() | 获取此IP地址的主机名。 |
static InetAddress | getLocalHost() | 返回本地主机的地址。 |
static InetAddress | getLoopbackAddress() | 返回环回地址。 |
int | hashCode() | 返回此IP地址的哈希码。 |
boolean | isAnyLocalAddress() | 用于检查InetAddress是否为通配符地址的实用例程。 |
boolean | isLinkLocalAddress() | 用于检查InetAddress是否为链接本地地址的实用程序例程。 |
boolean | isLoopbackAddress() | 用于检查InetAddress是否为环回地址的实用例程。 |
boolean | isMCGlobal() | 用于检查多播地址是否具有全局范围的实用例程。 |
boolean | isMCLinkLocal() | 用于检查多播地址是否具有链接范围的实用例程。 |
boolean | isMCNodeLocal() | 用于检查多播地址是否具有节点范围的实用例程。 |
boolean | isMCOrgLocal() | 用于检查多播地址是否具有组织范围的实用例程。 |
boolean | isMCSiteLocal() | 用于检查多播地址是否具有站点范围的实用程序例程。 |
boolean | isMulticastAddress() | 用于检查InetAddress是否为IP多播地址的实用程序例程。 |
boolean | isReachable(int timeout) | 测试该地址是否可达。 |
boolean | isReachable(NetworkInterface netif, int ttl, int timeout) | 测试该地址是否可达。 |
boolean | isSiteLocalAddress() | 用于检查InetAddress是否为站点本地地址的实用程序例程。 |
String | toString() | 将此IP地址转换为 String 。 |
(2)、URL类
类URL表示统一资源定位符,指向万维网上的“资源”的指针。 资源可以是文件或目录这样简单的东西,也可以是对更复杂的对象的引用,例如对数据库或搜索引擎的查询。 有关URL类型及其格式的更多信息,请访问: Types of URL
- 构造方法
构造器 | 描述 |
---|---|
URL(String spec) | 从 String表示创建 URL对象。 |
URL(String protocol, String host, int port, String file) | 创建 URL从指定对象 protocol , host , port号和 file 。 |
URL(String protocol, String host, int port, String file, URLStreamHandler handler) | 创建 URL从指定对象 protocol , host , port数, file ,和 handler 。 |
URL(String protocol, String host, String file) | 根据指定的 protocol名称, host名称和 file名称创建URL。 |
URL(URL context, String spec) | 通过解析指定上下文中的给定规范来创建URL。 |
URL(URL context, String spec, URLStreamHandler handler) | 通过使用指定上下文中的指定处理程序解析给定规范来创建URL。 |
- 所有方法
变量和类型 | 方法 | 描述 |
---|---|---|
boolean | equals(Object obj) | 将此URL与另一个对象进行相等性比较。 |
String | getAuthority() | 获取此 URL的权限部分。 |
Object | getContent() | 获取此URL的内容。 |
Object | getContent(类<?>[] classes) | 获取此URL的内容。 |
int | getDefaultPort() | 获取与此 URL关联的协议的默认端口号。 |
String | getFile() | 获取此 URL的文件名。 |
String | getHost() | 获取此 URL的主机名(如果适用)。 |
String | getPath() | 获取此 URL的路径部分。 |
int | getPort() | 获取此 URL的端口号。 |
String | getProtocol() | 获取此 URL的协议名称。 |
String | getQuery() | 获取此 URL的查询部分。 |
String | getRef() | 获取此 URL的锚点(也称为“引用”)。 |
String | getUserInfo() | 获取此 URL的userInfo部分。 |
int | hashCode() | 创建适合哈希表索引的整数。 |
URLConnection | openConnection() | 返回一个URLConnection实例表示由所引用的远程对象的连接URL 。 |
URLConnection | openConnection(Proxy proxy) | 与openConnection()相同,但连接将通过指定的代理进行; 不支持代理的协议处理程序将忽略代理参数并进行正常连接。 |
InputStream | openStream() | 打开与此 URL的连接并返回 InputStream以从该连接读取。 |
boolean | sameFile(URL other) | 比较两个URL,不包括片段组件。 |
static void | setURLStreamHandlerFactory(URLStreamHandlerFactory fac) | 设置应用程序的 URLStreamHandlerFactory 。 |
String | toExternalForm() | 构造此 URL的字符串表示 URL 。 |
String | toString() | 构造此 URL的字符串表示 URL 。 |
URI | toURI() | 返回与此URL等效的URI| |