《Java网络编程》摘要

应当在关闭流之前立即刷新输出所有流。否则,关闭流时留在缓冲区中的数据可能会丢失

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();

URL和URI

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

系统属性控制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

URLConnection

getContentType()
getContentLength()
getContentLengthLong()
getHeaderField(String)
getHeaderFieldKey(int)
getHeaderField(int)
getErrorStream()
如果预先不知道数据大小,可以使用分块传输编码方式 setChunkedStreamingMode() ; 分块传输编码会妨碍身份认证和重定向.

Socket

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)可能是无操作

ServerSocket

ServerSocketChannel, Selector,SocketChannel
测试ServerSocket是否打开
public static boolean isOpen(ServerSocket ss){
return ss.isBound() && !ss.isClosed();
}

SSLSocketFactory

SSLServerSocket, SSLServerSocketFactory
server.getSupportedCipherSuites()
server.getEnabledCipherSuites()

NIO

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

UDP

DatagramSocket,DatagramPacket
TCP端口和UDP端口没有任何关联。对于两个不同的程序,如果一个使用UDP而另一个使用TCP,那么它们可以使用相同的端口号。
UDP的发送和接收都使用DatagramSocket.接收数据时,指定端口号.发送数据时,DatagramSocket不指定端口号,端口号在DatagramPacket中指定.

IP组播

ping all-routers.mcast.net
MulticastSocket
ms.joinGroup(groupInetAdd);
ms.leaveGroup(groupInetAdd);
getLoopbackMode()返回值有问题(是反的)

问题

P263 : 三个Socket和转发优先级不知是怎么匹配的(代码中好像写错了,前面描述中高6位是DSCP,低两位是ECN, 而代码中是低6位DSCP,高两位ECN)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java网络编程是指使用Java语言进行网络通信和连接的技术。它可以实现网络服务器和客户端之间的数据传输和交互。 Java网络编程的基本原理是通过Java提供的网络编程API来创建网络应用程序。其中,常用的API有Socket、ServerSocket、URLConnection和URL等类。 Java网络编程的优点包括跨平台性强、能够处理多个连接、数据传输可靠性高以及支持各种网络协议等。通过Java网络编程技术,开发人员可以轻松地实现各种网络应用,如多人在线游戏、聊天程序、文件传输等。 当我们需要使用Java网络编程时,需要了解网络编程的基本知识和概念,如IP地址、端口号、TCP/IP协议等。在使用Java网络编程时,通常需要创建一个服务器端和一个客户端。服务器端通过ServerSocket类监听指定的端口,客户端通过Socket类与服务器端进行连接。一旦连接建立,就可以通过输入输出流进行数据的传输和交互。 对于Java网络编程的学习和应用,我们可以参考各种网络编程相关的书籍和教程,其中包括了《Java网络编程指南》、《深入理解Java网络编程》等。此外,也可以参考官方文档和在线资源,如Oracle官方网站等。 总之,Java网络编程是一项重要的技术,它允许我们创建强大的网络应用程序。通过学习和应用Java网络编程技术,我们能够更好地理解和应对网络通信和连接的需求,并且能够实现各种功能丰富的网络应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值