在JAVA网络编程中,使用客户端套接字(在javaweb中什么可以处理客
Java网络编程如何初始化套接字
不同的构造方法不仅带的参数不同,所具有的意义也不一样。下面分别解析这两个类的实例初始化过程。 ServerSocket 实例的初始化 ServerSocket 类提供了四个构造器: public Socket(String host, int port) throws UnknownHostException, IOException public Socket(InetAddress address, int port) throws IOException public Socket(String host, int port, InetAddress localAddr, int localPort) throws IOException public Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException public Socket() public Socket(Proxy proxy) 带参构造器用来创建已绑定的服务器套接字,也就是说构造成功后它就已经开始侦听指定的端口,且能够调用 accept() 方法来接受客户端连接。默认构造器则会创建未绑定的服务器套接字,构造成功后必须手动将其绑定到一个本地地址才能用,在绑定之前可以进行一些选项配置。 带参构造器 总的来说,带参构造器提供了三个参数: port 指定该服务器套接字所要侦听的本地端口。如果为 0,则由系统自动分配一个端口号,这必须以另外的方式让客户端获取端口号。 backlog 这个名词目前还没有合适的译名。底层系统的 TCP 实现会维护一个连接队列,该队列缓存了已被 TCP 处理完毕,但还没有被服务器套接字接受的客户端连接。一旦某个连接被接受(通过调用 accept() 方法),它就会被从队列中移除。backlog 参数就用于指定队列的最大长度,默认值为 50,但这个值只是一个建议,底层系统可能根据需要自动调整。如果队列满了,则其行为是平台相关的:微软的 WINSOCK 会拒绝新的连接,其他实现则什么都不做。严格地说,微软没有遵守规范,破坏了游戏规则…… bindAddr 一台机器可能会有多个本地 IP 地址,例如同时使用多块网卡。使用其他两个带参构造器时,该参数为 null,服务器套接字会在所有的本地 IP 地址(0.0.0.0 或 ::0)上侦听。如果希望只侦听一个地址,则可使用该参数。 默认构造器 如果使用默认构造器,在绑定地址前,还可以做些配置。绑定操作由两个 bind 方法定义,参数类似于带参构造器。配置项包括以下方面(都必须在绑定前配置): 设置是否重用本地地址 该选项由 setReuseAddress(boolean on) 方法配置,对应底层系统的 SO_REUSEADDR 套接字选项。JDK 没有定义该选项的默认值。如果该选项为 false,则在关闭 TCP 连接时,为了保证可靠性,该连接可能在关闭后的一段时间(大约两分钟)内保持超时状态(通常称为 TIME_WAIT 状态或 2MSL 等待状态),这段时间里无法将新建的服务器套接字绑定到同一个地址。在开发阶段,服务器可能不断重启,打开改选项会非常有用。 设置接收缓冲区大小 该选项由 setReceiveBufferSize(int size) 方法配置,对应底层系统的 SO_RCVBUF 套接字选项,单位是字节。《RFC 1323 - TCP Extensions for High Performance》将缓冲区大小定义为 64KB。该选项只是一个建议值,底层系统可能根据需要自行调整。 设置超时值 该选项由 setSoTimeout(int timeout) 方法配置,对应底层系统的 SO_TIMEOUT 套接字选项,单位是毫秒。默认值为 0。该选项影响 accept 方法的阻塞时间长度,如果超时将引发 SocketTimeoutException。如果设为 0,则表示永不超时。 设置性能首选项 性能首选项包括连接时间、延迟和带宽三个选项,由 setPerformancePreferences(int connectionTime, int latency, int bandwidth) 方法配置。这三个数值分别表示短连接时间、低延迟和高带宽的相对重要性,数值越大则越重要;其各自的绝对值没有意义。该方法的初衷是为了让 Java 能在用非 TCP/IP 实现的套接字环境下工作得更好,某些需要对网络进行调优的程序也可以将这三个首选项作为配置参数提供给用户。 Socket 实例的初始化 Socket 类提供了六个公共构造器(已过时的除外): public Socket(String host, int port) throws UnknownHostException, IOException public Socket(InetAddress address, int port) throws IOException public Socket(String host, int port, InetAddress localAddr, int localPort) throws IOException public Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException public Socket() public Socket(Proxy proxy) 前四个构造器创建已连接的客户端套接字,也就是说构造的时候就会去连接服务器。前两个构造器需要提供服务器的地址和端口作为参数,本地地址和端口由系统自动分配;后两个允许手动指定本地地址和端口,但极少使用。后两个构造器创建未连接的套接字,创建后需要调用 connect 方法手动连接,连接之前可以做一些配置。最后一个构造器接受一个代表代理服务其的 Proxy 对象,JDK 支持 HTTP 和 SOCKS(V4 或 V5)两种代理类型。 连接前的配置 在连接前,客户端套接字不仅像服务器套接字那样可以设置是否重用本地地址、缓冲区大小、超时值和性能首选项,还能够配置以下各项(都必须在连接前配置): 设置是否保持活跃 该选项由 setKeepAlive(boolean on) 方法配置,对应底层系统的 SO_KEEPALIVE 套接字选项。默认值为 false。如果打开该选项,则套接字会定期自动发送保持活跃的探测性消息,类似于心跳检测。根据《RFC 1122 - Requirements for Internet Hosts》的规定,保持活跃机制只是 TCP 的一个可选功能,如果支持的话,默认必须为 false,而且这种机制默认在成功建立连接后,且连续两小时没有数据传输的情况下才会被激活。从另一方面来看,通过套接字的 I/O 操作完全可以知道连接是否还有效,所以该选项的实用价值不大。 设置是否收发带外数据 该选项由 setOOBInline(boolean on) 方法配置,对应底层系统的 SO_OOBINLINE 套接字选项。默认值为 off。带外数据(Out-of-band Data)也叫做紧急数据,表示数据很重要,需要使用不同于发送普通数据的一个专用通道来发送。打开该选项后,就可以调用 sendUrgentData(int data) 方法发送一个字节的紧急数据。JDK 对带外数据只提供了有限支持,紧急数据将会和普通数据一起被收到,并且无法自动区分。该选项对应用开发人员意义不大。 设置是否从容关闭连接 该选项由 setSoLinger(boolean on, int linger) 方法配置,对应底层系统的 SO_LINGER 套接字选项。默认为 false。该选项只会影响套接字的关闭,其中的 linger 参数表示超时时间,单位为秒。如果打开改选项:如果将 linger 设为 0,则关闭套接字的时候,未发送的数据会被丢弃,且另一端会出现连接被同位体重置的异常;如果 linger 非 0,则关闭套接字的线程将被阻塞,直到数据全部发送或超时,超时后的行为与底层系统相关,JDK 无法控制。如果关闭该选项,则套接字正常关闭,数据也会全部发送。由于底层实现的差异性,不提倡应用开发人员打开该选项。 设置是否延迟发送数据 该选项由 setTcpNoDelay(boolean on) 方法配置,对应底层系统的 TCP_NODELAY TCP 选项。默认值为 off。打开该选项将禁用 Nagle 算法,TCP 包会立即发送;关闭该选项则会启用 Nagle 算法,多个较小的 TCP 包会被组合成一个大包一起发送,虽然发送延迟了,但有利于避免网络拥塞。默认为 false。该选项对实时性很强的程序可能有用,但一般的程序不需要关心。 设置流量类别 该选项由 setTrafficClass(int tc) 方法配置,对应底层系统的“流量类别”套接字属性。该选项用于向网络(例如路由器)提示从该套接字发送的包需要获取哪些服务类型,对本地 TCP 协议栈没有影响。IPv4 和 IPv6 分别定义了多个不同的值,例如 IPv4 将 0x08 定义为最大吞吐量,0x10 定义为最小延迟,等等。可以用或运算将多个值合并为一个选项。该选项用来调整性能,需要根据实际情况设置。由于只是建议值,可能被网络忽略。
在Java Socket网络编程中,ServerSocket 用于什么程序?
在 Java Socket 网络编程中,服务器使用 ServerSocket 来侦听传入的客户端连接。当客户端连接到服务器时,ServerSocket 会在服务器上创建一个新的套接字以与客户端通信,并为客户端提供新的输入流和输出流,分别用于读取和写入。ServerSocket 继续侦听新的传入客户端连接,并继续为每个连接的新客户端创建新的套接字和流。
java程序中使用tcp套接字编写服务端程序的套接字类是
ServerSocket。
“java程序中使用tcp套接字编写服务端程序的套接字类是”是《Java语言》复习资料的一道练习题,答案是ServerSocket。
Java是一门编程语言,是一门连接人与计算机的语言。
在javasocket网络编程中,开发基于udp协议的程序使用的套接字有哪些
Socket套接字,是由系统提供用于网络通信的技术(操作系统给应用程序提供的一组API叫做Socket API),是基于TCP/IP协议的网络通信的基本操作单元。基于Socket套接字的网络程序开发就是网络编程。
socket可以视为是应用层和传输层之间的通信桥梁;
传输层的核心协议有两种:TCP,UDP;socket API也有对应的两组,由于TCP和UDP协议差别很大,因此,这两组API差别也挺大。
分类:
Socket套接字主要针对传输层协议划分为如下三类:
流套接字:使用传输层TCP协议
TCP,即Transmission Control Protocol(传输控制协议),传输层协议;
TCP的特点:
有连接:像打电话,得先接通,才能交互数据;
可靠传输:传输过程中,发送方知道接收方有没有收到数据.(打电话就是可靠传输);
面向字节流:以字节为单位进行传输.(非常类似于文件操作中的字节流);
全双工:一条链路,双向通信;
有接收缓冲区,也有发送缓冲区。
大小不限
对于字节流来说,可以简单的理解为,传输数据是基于IO流,流式数据的特征就是在IO流没有关闭的情况下,是无边界的数据,可以多次发送,也可以分开多次接收。
数据报套接字:使用传输层UDP协议
UDP,即User Datagram Protocol(用户数据报协议),传输层协议。
UDP的特点:
无连接:像发微信,不需要接通,直接就能发数据;
不可靠传输:传输过程中,发送方不知道接收方有没有收到数据.(发微信就是不可靠传输);
面向数据报:以数据报为单位进行传输(一个数据报都会明确大小)一次发送/接收必须是一个完整的数据报,不能是半个,也不能是一个半;
全双工:一条链路,双向通信;
有接收缓冲区,无发送缓冲区;
大小受限:一次最多传输64k;
对于数据报来说,可以简单的理解为,传输数据是一块一块的,发送一块数据假如100个字节,必须一次发送,接收也必须一次接收100个字节,而不能分100次,每次接收1个字节。
原始套接字
原始套接字用于自定义传输层协议,用于读写内核没有处理的IP协议数据。
二、UDP数据报套接字编程
UDPSocket中,主要涉及到两类:DatagramSocket、DatagramPacket;
DatagramSocket API
DatagramSocket 创建了一个UDP版本的Socket对象,用于发送和接收UDP数据报,代表着操作系统中的一个socket文件,(操作系统实现的功能–)代表着网卡硬件设备的抽象体现。
DatagramSocket 构造方法:
方法签名 方法说明
DatagramSocket() 创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口(一般用于客户端)
DatagramSocket(int port) 创建一个UDP数据报套接字的Socket,绑定到本机指定的端口(一般用于服务端)
DatagramSocket 方法:
方法签名 方法说明
void receive(DatagramPacket p) 从此套接字接收数据报(如果没有接收到数据报,该方法会阻塞等待)
void send(DatagramPacket p) 从此套接字发送数据报包(不会阻塞等待,直接发送)
void close() 关闭此数据报套接字
DatagramPacket API
代表了一个UDP数据报,是UDP Socket发送和接收的数据报,每次发送/接收数据报,都是在传输一个DatagramPacket对象。
DatagramPacket 构造方法:
方法签名 方法说明
DatagramPacket(byte[] buf, int length) 构造一个DatagramPacket以用来接收数据报,接收的数据保存在字节数组(第一个参数buf)中,接收指定长度(第二个参数length)
DatagramPacket(byte[] buf, int offset, int length,SocketAddress address) 构造一个DatagramPacket以用来发送数据报,发送的数据为字节数组(第一个参数buf)中,从0到指定长度(第二个参数length)。address指定目的主机的IP和端口号
DatagramPacket 方法:
方法签名 方法说明
InetAddress getAddress() 从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址
int getPort() 从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获取接收端主机端口号
byte[] getData() 获取数据报中的数据
构造UDP发送的数据报时,需要传入 SocketAddress ,该对象可以使用 InetSocketAddress 来创建。
InetSocketAddress API
InetSocketAddress ( SocketAddress 的子类 )构造方法:
方法签名 方法说明
InetSocketAddress(InetAddress addr, int port) 创建一个Socket地址,包含IP地址和端口号
示例1:写一个简单的客户端服务程序,回显服务(EchoSever)
在这里插入图片描述
构建Socket对象有很多失败的可能:
端口号已经被占用,同一个主机的两个程序不能有相同的端口号(这就好比两个人不能拥有相同的电话号码);
此处,多个进程不能绑定同一个端口号,但是一个进程可以绑定多个端口,(这就好比一个人可以拥有多个手机号),一个进程可以创建多个Socket对象,每个Socket都绑定自己的端口。
每个进程能够打开的文件个数是有上限的,如果进程之间已经打开了很多文件,就可能导致此时的Socket文件不能顺利打开;
在这里插入图片描述
这个长度不一定是1024,假设这里的UDP数据最长是1024,实际的数据可能不够1024.
在这里插入图片描述
这里的参数不再是一个空的字节数组了,response是刚才根据请求计算的得到的响应,是非空的,DatagramPacket 里面的数据就是String response的数据。
response.getBytes().length:这里拿到的是字节数组的长度(字节的个数),而response.length得到的是字符的长度。
五元组
一次通信是由5个核心信息描述的:源IP、 源端口、 目的IP、 目的端口、 协议类型。
站在客户端角度:
源IP:本机IP;
源端口:系统分配的端口;
目的IP:服务器的IP;
目的端口:服务器的端口;
协议类型:TCP;
站在服务器的角度:
源IP:服务器程序本机的IP;
源端口:服务器绑定的端口(此处手动指定了9090);
目的IP:包含在收到的数据报中(客户端的IP);
目的端口:包含在收到的数据报中(客户端的端口);
协议类型:UDP;