lysu's java socket notes

41
Socket Socket 2011 2011

Upload: lysu

Post on 13-Jun-2015

1.578 views

Category:

Technology


3 download

DESCRIPTION

learning socket

TRANSCRIPT

Page 1: Lysu's Java Socket notes

SocketSocket

20112011 春春

Page 2: Lysu's Java Socket notes

StartStart !!

Page 3: Lysu's Java Socket notes

SocketSocket

应用程序需要和其他应用程序或模块进行应用程序需要和其他应用程序或模块进行交互交互

JavaJava 为应用程序通过网络交互提供了抽象为应用程序通过网络交互提供了抽象API- SocketAPI- Socket

Page 4: Lysu's Java Socket notes

基本概念基本概念 网络:网络是由多态计算机和他们之间的信道组成。计算机可以被分为网络:网络是由多态计算机和他们之间的信道组成。计算机可以被分为 HostHost 和和 RouterRouter ,, HostHost

是网络的用户,而是网络的用户,而 RouterRouter 可连起多个信道。我们通常所说的信道是指两个可连起多个信道。我们通常所说的信道是指两个 HostHost 间的通路间的通路 (( 以太以太网或网或 WIFI)WIFI)

网络包:网络包: packetpacket 包括供网络使用的控制信息和供程序使用的用户数据信息包括供网络使用的控制信息和供程序使用的用户数据信息 协议:规定了交互中信息的规格协议:规定了交互中信息的规格 TCP/IP TCP/IP 协议套件包括了 协议套件包括了 IPIP (标记路由)和在此之上的(标记路由)和在此之上的 TCP UDPTCP UDP 协议协议 TCP UDPTCP UDP 都通过端口(都通过端口( portport )来区分同一)来区分同一 hosthost 上的不通“地址”,都是端到端传输协议上的不通“地址”,都是端到端传输协议 TCPTCP 是面向连接的可靠的字节流通道,在交互前两应用得先握手建立连接再交互,是面向连接的可靠的字节流通道,在交互前两应用得先握手建立连接再交互, TCPTCP 能检测传能检测传

输过程中出现的故障并试图恢复,所以程序中不用操心输过程中出现的故障并试图恢复,所以程序中不用操心 UDPUDP 也是面向连接的,但不可靠,所以程序中可能需要处理丢包重复的错误也是面向连接的,但不可靠,所以程序中可能需要处理丢包重复的错误

Page 5: Lysu's Java Socket notes

地址地址 TCP/IPTCP/IP 通过通过 IPIP 地址和端口来区分应用地址和端口来区分应用 PortPort 是是 1616 位的二进制数字从位的二进制数字从 1~655351~65535 (( 00

保留保留 -- 代表任意端口)代表任意端口) 特殊的特殊的 IPIP

loopbackloopback 地址(地址( echoecho ) ) 127.0.0.1127.0.0.1 私有地址 以私有地址 以 1010 或或 192.168192.168 开头开头 link-locallink-local 地址 以地址 以 192.254192.254 开头 开头 routerrouter 对此对此

地址不做传递地址不做传递 多播地址 地址的第一个数字为多播地址 地址的第一个数字为 224224 或或 239239

Page 6: Lysu's Java Socket notes

名字名字 TCP/IPTCP/IP 不认识名字,只认识地址不认识名字,只认识地址 用名字更容易记住,也使地址的使用更透用名字更容易记住,也使地址的使用更透

明明 用名字的时系统做了额外的操作…用用名字的时系统做了额外的操作…用 TCPTCP

或或 UDPUDP 向向 DNSDNS 请求解析名字为地址请求解析名字为地址 其次系统也有本地的名字地址映射库可以其次系统也有本地的名字地址映射库可以

供本机使用供本机使用

Page 7: Lysu's Java Socket notes

客户端和服务器端客户端和服务器端 客户端向服务器发起请求,服务器对客户客户端向服务器发起请求,服务器对客户

端相应。。。端相应。。。 客户端必须知道服务器地址(包括端口),客户端必须知道服务器地址(包括端口),

服务器在接受客户端请求后有能力知道发服务器在接受客户端请求后有能力知道发起请求客户端的地址信息起请求客户端的地址信息

有一些常用的有一些常用的 PortPort 端口端口

Page 8: Lysu's Java Socket notes

SocketSocket 是神马是神马 SocketSocket 是对网络的抽象,应用程序可以通过他来发送和读取信息是对网络的抽象,应用程序可以通过他来发送和读取信息 流式流式 SocketSocket 使用使用 TCPTCP 来建立可靠通信服务来建立可靠通信服务 报文报文 SocketSocket 使用使用 UDPUDP 来提供高效通信,最大消息可以到来提供高效通信,最大消息可以到 6550065500 字字

节节 注意同一应用也可使用同一个注意同一应用也可使用同一个 SocketSocket

Page 9: Lysu's Java Socket notes

Socket TasteSocket Taste

Page 10: Lysu's Java Socket notes

Network AddressNetwork Address NetworkInterfaceNetworkInterface ::

通过其通过其 getNetworkInterfacesgetNetworkInterfaces 静态工厂方法取得网络接静态工厂方法取得网络接口对象口对象

也可以通过也可以通过 InetAddressInetAddress 来取得所属的来取得所属的 NetworkInterfaNetworkInterfacece

通过其可以取得接口名字和接口对应的网络地址列表通过其可以取得接口名字和接口对应的网络地址列表 可以通过实列方法来取得网关信息可以通过实列方法来取得网关信息

InetAddressInetAddress 代表具体的地址对象,所以可以取得所代表的名字和地址代表具体的地址对象,所以可以取得所代表的名字和地址 通过其静态方法可以取得对应名字的地址,通过其静态方法可以取得对应名字的地址, vice versavice versa !! 有可以用来检测地址属性的方法(有可以用来检测地址属性的方法( loopbackloopback 等),也可等),也可

以检查地址是否可达以检查地址是否可达

Page 11: Lysu's Java Socket notes

TCP SocketTCP Socket

Java Java 提供了两个提供了两个 SocketSocket 类:类: SocketSocket 和和 SServerSocketerverSocket

Socket Socket 代表代表 TCPTCP 连接的一端,连接的一端, TCPTCP 连接连接是双向的,并且各端都通过是双向的,并且各端都通过 IPIP 和和 PortPort 来来标识。标识。

在初始阶段客户端发出在初始阶段客户端发出 SocketSocket 请求,请求, SerServerver 在监听到请求后,同样取得在监听到请求后,同样取得 SocketSocket 连连接(所以服务器要两个都使用)接(所以服务器要两个都使用)

Page 12: Lysu's Java Socket notes

TCP TCP 客户端客户端 TCP TCP 客户端通过连接到一个在持续等待的客户端通过连接到一个在持续等待的 ServerServer 上进行工作上进行工作 三个步骤:三个步骤:

建立建立 SocketSocket 对象,此对象针对要请求的远程地址和端口对象,此对象针对要请求的远程地址和端口 通过通过 socketsocket 上的流对象进行交互上的流对象进行交互 关闭关闭 socketsocket 用用 closeclose 方法方法

Key operationKey operation :: SocketSocket 操作的数据得先转换为操作的数据得先转换为 bytebyte 数组数组 通过指定地址和端口来创建通过指定地址和端口来创建 socketsocket 对象对象

SocketSocket 构造函数有一个没有参数的方法使用时得显示用构造函数有一个没有参数的方法使用时得显示用 connectconnect 来连接来连接 发送使用发送使用 socketsocket 的的 outputstreamoutputstream 的的 writewrite 方法方法

如果对方如果对方 serverserver 没有没有 readread 会阻塞会阻塞 CloseClose 后自动后自动 flushflush

可以取得可以取得 socketsocket 的的 socketAddress(InetSocketAddress)socketAddress(InetSocketAddress) 使用使用 readread 方法从流中读取数据方法从流中读取数据

33 个参数:个参数: 用来接收的数组用来接收的数组 用来接受到的数据放在数组中的起始下标用来接受到的数据放在数组中的起始下标 一次读取时在数组中放置的最大字节数一次读取时在数组中放置的最大字节数 会导致阻塞直到接收到服务器回发的数据,一直循环直到末尾会导致阻塞直到接收到服务器回发的数据,一直循环直到末尾 -1-1 或对方关闭连接或对方关闭连接

注意:不要认为一个注意:不要认为一个 readread 接收一个接收一个 writewrite !请用循环将!请用循环将 readread 包起!包起!

Page 13: Lysu's Java Socket notes

TCP TCP 服务器服务器 服务器建立端点等待客户端请求并开启新的服务器建立端点等待客户端请求并开启新的 SocketSocket 进行处理进行处理 两个步骤:两个步骤:

通过指定端口号来建立通过指定端口号来建立 ServerSocketServerSocket ,此对象持续监听此端口,此对象持续监听此端口 重复:重复:

调用调用 acceptaccept 方法接收连接建立请求并返回方法接收连接建立请求并返回 socketsocket 对象对象 同样通过输入输出流和客户端交互同样通过输入输出流和客户端交互 完成后关闭完成后关闭 socketsocket 连接连接

Key operationKey operation :: 还是要注意还是要注意 readread 不一定可以完全读取到指定数组大小的数据,所以如果不一定可以完全读取到指定数组大小的数据,所以如果

要接着处理读取的到的信息,请使用要接着处理读取的到的信息,请使用 readread 的返回参数作为接下来工作的的返回参数作为接下来工作的大小!大小!

在指定端口时使用在指定端口时使用 00 端口会随机选取任意端口端口会随机选取任意端口 同样有个没有参数的同样有个没有参数的 serversocketserversocket 构造方法,同样等待之后用构造方法,同样等待之后用 bindbind 方方

法显示绑定之法显示绑定之 同样可以通过同样可以通过 ssss 对象获得本地端口信息对象获得本地端口信息

Page 14: Lysu's Java Socket notes

UDP SocketUDP Socket UDPUDP 是在是在 IPIP 之上的简单封装之上的简单封装 UDPUDP 可以检测一些影响传输的数据错误,并且抛可以检测一些影响传输的数据错误,并且抛弃这些错误弃这些错误

UDPUDP 不用发起连接,只用将数据封装为报文,并不用发起连接,只用将数据封装为报文,并标上目的地址和端口发送即可!标上目的地址和端口发送即可!

UDPUDP 不保证所发送的数据可以到达目的地,所以不保证所发送的数据可以到达目的地,所以效率更高,但使用应做排错准备效率更高,但使用应做排错准备

为啥使用为啥使用 UDPUDP 而不是而不是 TCPTCP呢?呢? 使用使用 UDPUDP 效率更高,不用建立连接效率更高,不用建立连接 UDPUDP 提供简单高效的基础来实现其他形式的传输提供简单高效的基础来实现其他形式的传输

Page 15: Lysu's Java Socket notes

报文报文 JavaJava 通过通过 DatagramPacketDatagramPacket 来提供报文抽象,来提供报文抽象,封装报文数据封装报文数据 包括地址,发送时是目的地址,接受时是源地址包括地址,发送时是目的地址,接受时是源地址 构造函数有地址参数的用于发送,没地址参数的多用构造函数有地址参数的用于发送,没地址参数的多用于接收报文用,当然在报文构建出来后任然有机会可于接收报文用,当然在报文构建出来后任然有机会可以改变和获取报文地址信息以改变和获取报文地址信息

报文中有可以获取设置发送读取长度的方法,同样也报文中有可以获取设置发送读取长度的方法,同样也可设置报文内容可设置报文内容

封装好的报文通过封装好的报文通过 DatagramSocketDatagramSocket 的的 sendsend 和和receivereceive 方法来发送和接收数据方法来发送和接收数据

Page 16: Lysu's Java Socket notes

UDP UDP 客户端客户端 同样也大致通过三步来建立同样也大致通过三步来建立 UDPUDP 客户端:客户端:

通过指定地址和端口来建立报文通过指定地址和端口来建立报文 DatagramPacketDatagramPacket 通过通过 DatagramSocketDatagramSocket 的的 sendsend 和和 receivereceive 方法来发方法来发

送和接收数据送和接收数据 DatagramSocketDatagramSocket 也同样可以指定端口和地址(通过也同样可以指定端口和地址(通过

构造函数或构造函数或 connectconnect 方法),因此也可以从中获取地方法),因此也可以从中获取地址、端口、超时等信息址、端口、超时等信息

关闭关闭 DatagramSocketDatagramSocket 释放资源释放资源 UDPUDP 不保证数据传输的可靠性,所以调用不保证数据传输的可靠性,所以调用 receivreceiv

ee 后可能永远阻塞,因此一般要用后可能永远阻塞,因此一般要用 setSoTimeoutsetSoTimeout来设置超时防止不必要的永远阻塞来设置超时防止不必要的永远阻塞

Page 17: Lysu's Java Socket notes

UDP UDP 服务器服务器UDPUDP 是不用连接,所以不需建立连接的步骤是不用连接,所以不需建立连接的步骤 也是三步也是三步

通过指定端口建立通过指定端口建立 DatagramSocketDatagramSocket ,或可选,或可选的本机地址,这时已做好等待请求的准备的本机地址,这时已做好等待请求的准备

通过调用通过调用 DatagramSocketDatagramSocket 上的上的 receivereceive 方法方法接收报文接收报文

如有需要可以再次通过如有需要可以再次通过 sendsend 的方法回发数据的方法回发数据

Page 18: Lysu's Java Socket notes

UDPUDP 收发区别观收发区别观 与与 TCPTCP 不同,不同, UDPUDP 保留信息边界,一次保留信息边界,一次 receivreceiv

ee基本对应一次基本对应一次 sendsend TCPTCP 提供错误检测,所以在发送前有提供错误检测,所以在发送前有 bufferbuffer ,,

而而 UDPUDP 没有,所以直接发送数据到底层信道没有,所以直接发送数据到底层信道 在接收到数据后都是通过一个队列来排队取包,在接收到数据后都是通过一个队列来排队取包,

TCPTCP 能保证包完整,而能保证包完整,而 UDPUDP 只是取指定长度的只是取指定长度的包,其他包都丢弃,所以最好把包的长度设为待包,其他包都丢弃,所以最好把包的长度设为待发送包中的最大长度发送包中的最大长度

注意注意 GetDataGetData返回整个包,而不管返回整个包,而不管 offsetoffset 和和 lenlengthgth

Page 19: Lysu's Java Socket notes

细看收发数据细看收发数据

Page 20: Lysu's Java Socket notes

规则规则 人们使用网络来交换数据,就必然要求对人们使用网络来交换数据,就必然要求对

数据字节进行编码方便协同数据字节进行编码方便协同 传送的信息不可避免的需要协定信息序列传送的信息不可避免的需要协定信息序列

字节表现方式字节表现方式 ------ 也就是编码也就是编码 协议规定了数据格式和意义协议规定了数据格式和意义 对于特定应用使用的协议叫做应用协议对于特定应用使用的协议叫做应用协议 TCPTCP 要求使用要求使用 8bit8bit 的块来收发数据也就是的块来收发数据也就是

1byte1byte

Page 21: Lysu's Java Socket notes

信息编码信息编码SocketSocket 只接受只接受 javajava 中的一种类型中的一种类型 ---bytes---bytes

作为发送接收处理类型对于其他?作为发送接收处理类型对于其他?

Page 22: Lysu's Java Socket notes

整数编码整数编码 我们已经知道我们已经知道 socketsocket 可以直接发送可以直接发送 bytebyte (( 1-251-25

55 ),但对于大于),但对于大于 11 字节的整数类型,我们同样字节的整数类型,我们同样可以通过编码后来发送,但是收发者首先得达成可以通过编码后来发送,但是收发者首先得达成一定写协定:一定写协定: 类型的大小类型的大小 字节的发送顺序(从低到高,从高到低)字节的发送顺序(从低到高,从高到低) 发送的数字是否有符号(发送的数字是否有符号( javajava 中的数字全是有符号—中的数字全是有符号—存储:补码)存储:补码)

可以自己实现编码并发送 位移可以自己实现编码并发送 位移 ++掩码掩码 JavaJava 也提供了内建的编码方式,可以串起也提供了内建的编码方式,可以串起 ByteAByteA

rrayOutputStreamrrayOutputStream 和和 DataOutputStreamDataOutputStream 来达来达到目的到目的

Page 23: Lysu's Java Socket notes

字符串和文本编码字符串和文本编码 众所周知使用众所周知使用 stringstring 的的 getBytesgetBytes 方法可以得到方法可以得到

字符串的字节数组表现字符串的字节数组表现 字符串内部由字符串内部由 charchar 数组表示,而数组表示,而 charchar又被表现又被表现

为整数,符号和数字的映射就是字符编码集为整数,符号和数字的映射就是字符编码集 对于用较小数字表示的字符编码集可以方便的使对于用较小数字表示的字符编码集可以方便的使

用用 bytebyte 来直接传输,但对于较大数字的编码,收来直接传输,但对于较大数字的编码,收发方需相互协调,协定编码方案发方需相互协调,协定编码方案

编码后的字符和编码方案一起被称为编码后的字符和编码方案一起被称为 charsetcharset 可以在可以在 getBytesgetBytes 方法调用时加入字符名字作为参方法调用时加入字符名字作为参

数来指定字符集数来指定字符集

Page 24: Lysu's Java Socket notes

组合组合 I/O StreamI/O Stream

For Java’s Input and Output stream, For Java’s Input and Output stream, we can simply chain them to get the we can simply chain them to get the more powerful streammore powerful stream

Page 25: Lysu's Java Socket notes

定界解析定界解析 经经 TCP socketTCP socket 发送的数据得在接收端进行解析,发送的数据得在接收端进行解析,

解析时接收者得知道数据流的具体起始位置(不能解析时接收者得知道数据流的具体起始位置(不能多收也不能少收)多收也不能少收)

一般有两种解决办法一般有两种解决办法 使用定界符,再发送数据主体后发送一个双方协商好了使用定界符,再发送数据主体后发送一个双方协商好了

的特殊符号进行识别(的特殊符号进行识别( read -1read -1 )) [[ 注意发送信息里这个注意发送信息里这个符号要检测符号要检测 ]]

使用显式的边界数据,在发送信息前,先发送数据的长使用显式的边界数据,在发送信息前,先发送数据的长度数据,再发送主体信息度数据,再发送主体信息

UDP socketUDP socket 可以自己定界,所以不需要此步骤哈可以自己定界,所以不需要此步骤哈

Page 26: Lysu's Java Socket notes

Nice ExampleNice Example

Page 27: Lysu's Java Socket notes

SocketSocket 进阶主题进阶主题开始发力开始发力

Page 28: Lysu's Java Socket notes

NN 任务任务 在不使用多任务的情况下,服务器同一时在不使用多任务的情况下,服务器同一时刻只能处理单一客户的请求,并顺序处理,刻只能处理单一客户的请求,并顺序处理,如果要同时处理则要求使用多个线程对个如果要同时处理则要求使用多个线程对个个客户同时分别相应!个客户同时分别相应!

可以使用每客户一线程和线程池的策略可以使用每客户一线程和线程池的策略

Page 29: Lysu's Java Socket notes

复习线程复习线程 通过继承通过继承 ThreadThread 的子类,通过重写的子类,通过重写 runrun

方法并实列化方法并实列化 或通过产生实现了或通过产生实现了 RunnableRunnable 的对象,并的对象,并

传递给传递给 ThreadThread 的构造函数的构造函数 使用使用 startstart 方法来启动线程方法来启动线程 如果线程有访问共享资源,则要通过加锁如果线程有访问共享资源,则要通过加锁

或无锁方法保持正确使用或无锁方法保持正确使用

Page 30: Lysu's Java Socket notes

日志日志 在同时为多用户处理时日志就变得非常重要,现在同时为多用户处理时日志就变得非常重要,现

在有多种日志方案在有多种日志方案 log4j commons-logger slf4jlog4j commons-logger slf4j等…现讨论下等…现讨论下 javajava内建的内建的 LoggerLogger

通过静态工厂方法通过静态工厂方法 Logger.getLoggerLogger.getLogger 来取得实来取得实列列

LevelLevel 对象用来表示消息的重要性,可以使用简对象用来表示消息的重要性,可以使用简便方法来直接使用不同的便方法来直接使用不同的 levellevel ,此外可以在,此外可以在 loglog方法中传入参数方法中传入参数

可以通过设定不通的可以通过设定不通的 HandlerHandler 来让日志记录到不来让日志记录到不同的地方同的地方

Page 31: Lysu's Java Socket notes

线程池线程池 在不使用线程池的时候对每次请求的新分配一个在不使用线程池的时候对每次请求的新分配一个线程,这样会导致过多的线程,过多的线程带来线程,这样会导致过多的线程,过多的线程带来的是资源(的是资源( stackstack )的消耗,和频繁的上下文切)的消耗,和频繁的上下文切换…换…

通过线程池来限制线程总数,当请求时,从线程通过线程池来限制线程总数,当请求时,从线程池中取得线程,用完后放回池中,当池中线程不池中取得线程,用完后放回池中,当池中线程不足时,则先排队等待分配足时,则先排队等待分配

自己分配线程池中的线程数,不太容易…自己分配线程池中的线程数,不太容易… 通过使用通过使用 java.util.concurrent.Executorjava.util.concurrent.Executor 来执来执

行,可以使用不通的池策略,并且如果某线程终行,可以使用不通的池策略,并且如果某线程终止,他会新创建线程来在池里补上,并且他们阻止,他会新创建线程来在池里补上,并且他们阻塞是在塞是在 ExecutorExecutor 中阻塞…不在程序中哈中阻塞…不在程序中哈

Page 32: Lysu's Java Socket notes

阻塞与超时阻塞与超时 在在 socketsocket 基本操作中存在各种阻塞,先来基本操作中存在各种阻塞,先来看这些阻塞操作,并看看如何减轻阻塞看这些阻塞操作,并看看如何减轻阻塞

accept(), read(), receive()accept(), read(), receive() ,可以通过,可以通过 sesetSoTimeouttSoTimeout 来设置超时,之后在使用来设置超时,之后在使用 socsocketket 时可以通过时可以通过 availableavailable 方法来检测是否方法来检测是否可用可用

连接服务器,可以不使用连接服务器,可以不使用 socketsocket 构造函数,构造函数,换而使用换而使用 connectconnect 方法并指定超时方法并指定超时

writewrite 的阻塞不可避免 的阻塞不可避免 - -!- -!

Page 33: Lysu's Java Socket notes

多个接收者多个接收者 考虑一对多的情况,相对于自己对每个接收者发送多份数据,依靠网考虑一对多的情况,相对于自己对每个接收者发送多份数据,依靠网

络特性只发送一份数据并由网络分发给接收者络特性只发送一份数据并由网络分发给接收者 两种一对多策略两种一对多策略

Broadcast Broadcast 每个宿主机都收到数据的一份拷贝每个宿主机都收到数据的一份拷贝 和普通和普通 UDPUDP 一样,但是使用一样,但是使用 broadcastbroadcast 地址地址 (255.255.255.255)(255.255.255.255) ,消息被发,消息被发

送到同一网段的所有送到同一网段的所有 hosthost 上但不会被上但不会被 routerrouter 转发转发 Multicast Multicast 数据发送到多播地址,并且由网络来广播,并可以在发送时数据发送到多播地址,并且由网络来广播,并可以在发送时

指定可以接收的指定可以接收的 hosthost 可以指定接收的范围可以指定接收的范围 通过使用通过使用 MulticastSocket(DatagramSocketMulticastSocket(DatagramSocket 子类子类 )) 在发送方可以通过在发送方可以通过 setTimeToLivesetTimeToLive 来限制接收者距离(发送可以不使用来限制接收者距离(发送可以不使用 MulMul

ticastSocketticastSocket )) 接收者一定得用接收者一定得用 MulticastSocketMulticastSocket ,并,并 joinGroupjoinGroup 才可以接收才可以接收

注意:只有注意:只有 UDPUDP才支持才支持 broadcastbroadcast 或或 multicastmulticast ,, UDPUDP 可以可以 通过单独的指定地址和端口的接入通过单独的指定地址和端口的接入 通过通过 multicastmulticast 到指定的组的指定端口接入到指定的组的指定端口接入 通过通过 broadcastbroadcast 可以到达的地址端口接入可以到达的地址端口接入

Page 34: Lysu's Java Socket notes

控制默认行为控制默认行为 KeepAliveKeepAlive

开启后会定时发包检测其他节点是否可用,不可用则会自动关闭(默认未开启此功能)开启后会定时发包检测其他节点是否可用,不可用则会自动关闭(默认未开启此功能) 收发缓冲区大小收发缓冲区大小

对对 socketsocket、、 datagramdatagram 通过通过 ReceiveBufferSizeReceiveBufferSize 来建议分配指定大小缓冲来建议分配指定大小缓冲 对对 serverSocketserverSocket 的的 ReceiveBufferSizeReceiveBufferSize 的设定则是和之后的设定则是和之后 acceptaccept 出来的出来的 socketsocket 相关相关

超时超时 通过通过 setSoTimeoutsetSoTimeout 来设定超时,设为来设定超时,设为 00则表示永不超时则表示永不超时

地址复用地址复用 Socket, ServerSocket, DatagramSocketSocket, ServerSocket, DatagramSocket 的的 ReuseAddressReuseAddress 属性来设置属性来设置

消除缓冲延迟消除缓冲延迟 TCPTCP希望避免小数据包的发送,他会先做缓冲然后一并发送希望避免小数据包的发送,他会先做缓冲然后一并发送 当你要改变这一功能时可以通过当你要改变这一功能时可以通过 socketsocket 的的 TcpNoDelayTcpNoDelay 属性属性

紧急数据紧急数据 通过通过 sendUrgentDatasendUrgentData 方法发送,并在接收者处设置方法发送,并在接收者处设置 OOBInlineOOBInline ,, javajava 中这个不太常用,可以通过次序排在前面发送来达到中这个不太常用,可以通过次序排在前面发送来达到

延迟关闭延迟关闭 通常在关闭通常在关闭 socketsocket 时不管时不管 bufferbuffer里是否有数据,可以通过设置里是否有数据,可以通过设置 SoLingerSoLinger 来改变这一特性,使之等待发送完毕,或直到超时来改变这一特性,使之等待发送完毕,或直到超时

广播授权广播授权 有的系统需要显示要求授权,显示设置有的系统需要显示要求授权,显示设置 BroadcastBroadcast 可以达到可以达到

交通类型交通类型 通过设定通过设定 TrafficClassTrafficClass 可以然网络据此进行特殊处理,但不一定保证一定能处理 可以然网络据此进行特殊处理,但不一定保证一定能处理 - -- -

协议建议协议建议 可以通过可以通过 PerformancePreferencesPerformancePreferences 来建议在特定数据时使用不通协议来建议在特定数据时使用不通协议

Page 35: Lysu's Java Socket notes

关闭连接关闭连接 关闭连接很重要,通过关闭,接收者才能关闭连接很重要,通过关闭,接收者才能

知道发送方已经发送完毕知道发送方已经发送完毕 但考虑这样一个情况,当发送者发起请求,但考虑这样一个情况,当发送者发起请求,

服务器在接收请求处理后返回给请求者…服务器在接收请求处理后返回给请求者…如此发送者在发送后就不能立刻关闭如此发送者在发送后就不能立刻关闭 socksocketet ,这样就没法收到!,这样就没法收到!

因此可以对因此可以对 socketsocket 的的 inputinput 和和 outputoutput 分分开开 shutdownshutdown !!!!!!

Page 36: Lysu's Java Socket notes

NIONIO

java.nio.channelsjava.nio.channelsjava.niojava.nio

Page 37: Lysu's Java Socket notes

为啥需要她为啥需要她 每个请求一线程的模式经过使用线程池后仍然在处理量大时力不从心每个请求一线程的模式经过使用线程池后仍然在处理量大时力不从心 对待处理的请求进行排队或区分优先级对待处理的请求进行排队或区分优先级 在使用多线程时对资源进行同步带来的编程复杂性,和对程序整体的在使用多线程时对资源进行同步带来的编程复杂性,和对程序整体的内在性能损耗内在性能损耗

SoSo !! 我们需要找到一种方法,从中可以处理多个客户端,并在需要服务时我们需要找到一种方法,从中可以处理多个客户端,并在需要服务时

知道哪个客户需要被服务知道哪个客户需要被服务 ChannelChannel 代表一个可被投票的和代表一个可被投票的和 socketsocket 类似的处理目标,他可以被类似的处理目标,他可以被

注册上注册上 SelectorSelector 通过通过 SelectorSelector 的的 selectselect 方法,就可以知道被注册的那组方法,就可以知道被注册的那组 channelchannel 哪哪

个需要被服务,需要啥服务个需要被服务,需要啥服务 还有就是还有就是 BufferBuffer ,一个大小固定的用来传递数据的数据容器,通过,一个大小固定的用来传递数据的数据容器,通过

bufferbuffer 对数据的读写都暴露在程序员面前,并且通过对数据的读写都暴露在程序员面前,并且通过 bufferbuffer 可以直可以直接和底层系统进行映射对应(减少了不必要的拷贝移动)接和底层系统进行映射对应(减少了不必要的拷贝移动)

Page 38: Lysu's Java Socket notes

Channels with BuffersChannels with Buffers

ChannelChannel 抽象了对设备的连接,对于抽象了对设备的连接,对于 TCPTCP来说,可以使用来说,可以使用 ServerSocketChannelServerSocketChannel 和和SocketChannelSocketChannel

ChannelChannel 一般使用静态工厂方法来创建一般使用静态工厂方法来创建 通过通过 bufferbuffer 来读写数据,来读写数据, bufferbuffer 是大小是大小固定、并且内建状态跟踪机制的数据容器,固定、并且内建状态跟踪机制的数据容器,BufferBuffer 是抽象类,具体功能由子类实现,是抽象类,具体功能由子类实现,并且他也是通过静态工厂方法并且他也是通过静态工厂方法 allocateallocate 创创建或者通过建或者通过 wrapwrap 来包装现有数组来包装现有数组

Page 39: Lysu's Java Socket notes

非阻塞非阻塞 通过通过 nionio 的的 channelchannel ,我们可以达到非阻,我们可以达到非阻塞塞

通过通过 configureBlockingconfigureBlocking 方法来配置非阻方法来配置非阻塞塞

配置配置 channelchannel 非阻塞后,各种之前阻塞的非阻塞后,各种之前阻塞的操作会立即返回不在阻塞,但因此在程序操作会立即返回不在阻塞,但因此在程序中就需要自己检测中就需要自己检测 channelchannel 的状态,来进的状态,来进行下一步操作行下一步操作

Page 40: Lysu's Java Socket notes

SelectorsSelectors

SelectorSelector 实时的检测所注册的那组实时的检测所注册的那组 channchannelel 的的 IOIO状态状态

同样通过同样通过 openopen 静态工厂创建,之后在静态工厂创建,之后在 chachannelnnel 上注册,之后调用上注册,之后调用 selectselect 方法,等待方法,等待channelchannel 可以进行可以进行 IOIO 操作或发生超时,操作或发生超时, sselectelect 返回等待处理的返回等待处理的 channelchannel 数(没有数(没有时返回时返回 00 ))

Page 41: Lysu's Java Socket notes

细看 细看 BufferBuffer