应当在关闭流之前立即刷新输出所有流。否则,关闭流时留在缓冲区中的数据可能会丢失
java.security.DigestInputStream流关闭后,依然可以获取消息摘要
mark()方法标记流的当前位置,reset()方法把流重置到标记的位置. markSupported(),
PRintStream问题 1. println()的输出是与平台有关的 2. PrintStream假定使用所在平台的默认编码方式 3. PrintStream吞掉了所有异常
writeUTF()有问题????[Java网络编程P49]
DataInputStream.readLine()和BufferedReader.readLine()有bug
OutputStreamWriter有返回对象编码方式的方法: public String getEncoding()
线程调度 1. 抢占式: 一个线程轮询到CPU时,会暂停当前线程 2. 协作式: 正在运行的线程自己暂停,才会将CPU控制权交给其他线程
线程暂停锁释放情况 1. I/O阻塞不会释放线程已经拥有的锁 2. Thread.yield()并不会释放线程拥有的锁 3. Thread.sleep()进入休眠,仍然拥有它已经获得的锁 4. 调用对象的等待时,调用它的线程会释放所等待的对象的锁(但不会释放它所拥有的其他对象的锁)
InetAddress
ip地址访问: byte[] address = {107, 23, (byte)216, (byte)196}; InetAddress lessWrong = InetAddress.getByAddress(address); InetAddress lessWrongWithname = InetAddress.getByAddress(“lesswrong.com”, address);
控制DNS缓存时间: 用系统属性networkaddress.cache.ttl和networkaddress.cache.negative.ttl来控制缓存
给定地址,找出主机名: InetAddress ia = InetAddress.getByName(“208.201.239.100”); System.out.println(ia.getCanonicalHostName());
地址长度: byte[] address = ia.getAddress(); if(address.length == 4) return Version4; else if(address.length == 16) return Version6;
通配地址(wildcard address): IPv4中: 0.0.0.0 IPv6中: 0:0:0:0:0:0:0:0也写为:: 回环地址(loopback address): IPv4中: 127.0.0.1 IPv6中: 0:0:0:0:0:0:0:1也写为::1 测试可达性: isReachable()
NetworkInterface类 NetworkInterface对象表示物理硬件和虚拟地址 NetworkInterface ni = NetworkInterface.getByName(“eth0”); NetworkInterface.getByInetAddress(local); Enumeration< NetworkInterface > = NetworkInterface.getNetworkInterfaces();
NetworkInterface eth0 = NetworkInterface.getByName(“eth0”); Enumeration addresses = eth0.getInetAddresses();
java.net.URI类 只标识资源 java.net.URL类 既能标识资源,又能获取资源 openStream(): 直接打开文件流 openConnection(): 打开链接,可以访问服务器发送的所有数据,包括协议的元数据,HTTP首部以及原始HTML getQuery()返回URL的查询字符串 URL的equals可能是一个阻塞的I/O操作. 应当避免将URL存储在依赖equals的数据结构中,如java.util.HashMap.而使用java.net.URI URL.toURI() URI.toURL() URI.create() URI isOpaque() 不分层的URI URLEncoder.encode(“str”, “UTF-8”); 它对URL或查询字符串中使用的特殊字符(如/和=)和需要编码的字符不加区分 设置代理服务器的域名或IP地址: System.setProperty(“http.proxyHost”, “192.168.254.254”); 设置代理服务器的端口: System.setProperty(“http.proxyPort”, “9000”); 禁止代理: System.setProperty(“http.nonProxyHosts”, “xml.oreilly.com”); 对应ftp代理设置: ftp.proxyHost, ftp.proxyPort, ftp.nonProxyHosts TCP的SOCKS代理: socksProxyHost,socksProxyPort ; SOCKS没有提供禁止代理选项,是”全有或全无”的选择 Proxy类: Proxy.Type.DIRECT, Proxy.Type.HTTP, Proxy.Type.SOCKS SocketAddress address = new InetSocketAddress(“proxy.example.com”, 80); Proxy proxy = new Proxy(Proxy.Type.HTTP, address); Authenticator:
系统属性控制HTTP Keep-Alive: http.keepAlive http.maxConnections http.keepAlive.remainingData sun.net.http.errorstream.enableBuffering sun.net.http.errorstream.bufferSize sun.net.http.errorstream.timeout
getContentType() getContentLength() getContentLengthLong() getHeaderField(String) getHeaderFieldKey(int) getHeaderField(int) getErrorStream() 如果预先不知道数据大小,可以使用分块传输编码方式 setChunkedStreamingMode() ; 分块传输编码会妨碍身份认证和重定向.
shutdownInput() shutdownOutput() 即使半关闭连接,或将连接的两半都关闭,使用结束后仍需要关闭该socket /etc/services 查看哪些服务驻留在哪个端口
设置TCP_NODELAY为true,setTcpNoDelay(true)关闭Socket的缓冲, 所有包一旦就绪就会发送.
SO_LINGER选项指定Socket关闭时如何处理尚未发送的数据报。SO_LINGER开启,close()会阻塞指定的秒数,直到数据发送完毕或超时(指定为0秒,则close()直接超时)。如果是超时,则所有未发送的数据包都将丢弃。当SO_LINGER关闭,close()方法立即返回,但系统仍会尝试发送剩余的数据. 也即开启SO_LINGER,则Socket关闭如果超过指定时间,则丢弃未发送的数据。禁用SO_LINGER,Socket关闭,则后台处理发送未处理的数据.
setReceiveBufferSize()/setSendBufferSize(): 网络本身对最大带宽是有限制的。将缓冲区大小设置过高,程序会试图以过高的速度发送和接收数据,而网络来不及处理,就会导致拥塞、丢包和性能下降。因此,要得到最大带宽,需要让缓冲区大小与连接的延迟匹配,使它稍小于网络的带宽. 尽管看起来应该能独立地设置发送和接收缓冲区,但实际上缓冲区通常会设置为二者中较小的一个.
如果打开了SO_KEEPALIVE,客户端偶尔会通过一个空闲连接发送一个数据包,已确保服务器未崩溃.如果没有SO_KEEPALIVE,不活动的客户端可能会永远存在下去,而不会注意到服务器已经崩溃.
TCP包括一个可以发送单字节带外“紧急”数据的特性。这个数据会立即发送。此外,当接收方收到紧急数据时会得到通知,在处理其他 已收到的数据之前,可以选择先处理这个紧急数据. sendUrgentData(int)会立即发送参数中的最低位字节.如果必要,当前缓存中的所有数据将首先刷新输出
如果Socket绑定到一个已知端口,会阻止所有其他Socket同时使用这个端口。如果开启SO_REUSEADDR(默认为关闭),就允许另一个Socket绑定到这个端口,即使此时仍有可能存在前一个Socket未接收的数据. 之前连接的Socket和重用老地址的新Socket都必须设置SO_REUSEADDR为true,才能生效.
服务类型存储在IP首部中一个名为IP_TOP的8位字段中.业务流类型以0到255之间的int给出。由于这个值要复制到TCP首部中的一个8位字段,所以只使用这个int的低字节,超出这个范围的值会导致IllegalArgumentException异常.
setTrafficClass()/setPerformancePreferences(int,int,int)可能是无操作
ServerSocketChannel, Selector,SocketChannel 测试ServerSocket是否打开 public static boolean isOpen(ServerSocket ss){ return ss.isBound() && !ss.isClosed(); }
SSLServerSocket, SSLServerSocketFactory server.getSupportedCipherSuites() server.getEnabledCipherSuites()
client.read(buffer); buffer.flip(); out.write(buffer); buffer.clear(); flip()方法将限度设置为当前位置,位置设置为0: public final Buffer flip() 希望排空刚刚填充的缓冲区时可以调用此方法.channel.write(…)前 ByteBuffer.allocate() ByteBuffer.wrap() 修改数组会反映到缓冲区,反之亦然,所以对数组操作结束前不要包装数组 buffer.get() 获取一个数据,并将position加1 get(int), put(int,byte) 不改变位置 if(buffer.order().equals(ByteOrder.BIG_ENDIAN)){ buffer.order(ByteOrder.LITTLE_ENDIAN); } remaining()方法返回缓冲区中当前位置与限度之间的元素数。如果剩余元素大于0,hasRemaining()方法返回true. 位置达到限度时,hasRemaining()返回false. SocketChannel类只有读/写ByteBuffer的方法。它无法读/写任何其他类型的缓冲区. 示例中两个缓冲区(原ByteBuffer和视图IntBuffer)的位置和限度是独立的,必须分别考虑. 非阻塞模式不能保证缓冲区在排空后仍能以int,double或char等类型的边界对齐.向非阻塞通道写入一个int或double 的部分是完全有可能的。使用非阻塞I/O时,在向视图缓冲区放入更多数据前,要确保检查这个问题。 压缩缓冲区?????怎么用?????
下面的循环会一直读取数据,直到缓冲区填满或者检测到流末尾为止: while(buffer.hasRemaining() && channel.read(buffer) !=-1);
SelectionKey.OP_ACCEPT SelectionKey.OP_CONNECT SelectionKey.OP_READ SelectionKey.OP_WRITE
DatagramSocket,DatagramPacket TCP端口和UDP端口没有任何关联。对于两个不同的程序,如果一个使用UDP而另一个使用TCP,那么它们可以使用相同的端口号。
ping all-routers.mcast.net MulticastSocket ms.joinGroup(groupInetAdd); ms.leaveGroup(groupInetAdd); getLoopbackMode()返回值有问题(是反的)
P263 : 三个Socket和转发优先级不知是怎么匹配的(代码中好像写错了,前面描述中高6位是DSCP,低两位是ECN, 而代码中是低6位DSCP,高两位ECN)
新闻热点
疑难解答