java支持的协议只有TCP、UDP,以及建立在TCP和UDP之上的应用层协议.
Internet地址:最低地址用于标识网络本身,最高地址是这个网络的一个广播地址。
防火墙过滤:一般是基于网络地址和端口的;防火墙一般工作于传输层或网际层。
代理服务器:一般工作于应用层;一般公司使用代理服务器跟踪员工的web情况.
PrintStream是有害的,网络编程应该避免使用:
1, println()输出的行分隔符与平台有关;但是大多数网络协议,明确指定行以回车/换行结束;所以应该显式地写入协议所需的行结束符。
2, PrintStream假定使用所在平台的默认编码。
3, PrintStream吞掉了所有异常。
一般服务器通过线程池来处理短连接,如果一个应用要同时保持数千个长连接,就要考虑异步IO (基于通道和缓冲区) 而不是线程。
当采用多线程通信的时候:不要尝试在主线程中询问子线程的结果,因为不确定子线程是否结束;而是要在子线程完成后回调 callback 创建者的方法。
可以使用线程池来实现多线程:
class FindMaxTask implements Callable
重写call方法,此方法可以返回任意类型
}
FindMaxTask task1 = new FindMaxTask();
FindMaxTask task2 = new FindMaxTask();
ExecutorService service = Executors.newFixedThreadPool(2);
Future
Future
return Math.max(future1.get(), future2.get());
向ExecutorService 提交Callable任务,对于每个Callable任务,会分别得到一个Future。之后可以向Future请求得到任务的结果。如果结果已经准备就绪,就会立即得到
这个结果;如果还没有准备好,轮询线程会阻塞,直到结果准备就绪。这种做法,可以按你需要的顺序得到需要的答案。
调用future1.get()时,这个方法会阻塞,等待task1完成;然后才调用future2.get(),也有可能task2线程已经结束了,此时会立刻得到结果。
防止死锁:避免不必要的同步;若确实需要同步,要保持同步块尽可能的小;多个线程确保以相同的顺序请求共享资源。
线程调度:抢占式、协作式.
所有java虚拟机都确保在不同的优先级之间使用抢占式线程调度。
当线程wait的时候,其他线程调用这个线程的interrupt()方法,这将导致一个InterruptedException异常,并在捕获这个异常的catch块内继续执行。
不过,在抛出异常前线程要重新获得所等待对象的锁,所以调用interrupt()方法后,该线程可能仍要阻塞一段时间。
InetAddress类:
InetAddress address = InetAddress.getByName("www.hao123.com");
此方法会建立与本地DNS服务器的一个连接;由于DNS查找的开销很大,InetAddress类会缓存查找的结果。
InetAddress address = InetAddress.getByName("208.201.239.100");
NetworkInterface类:
表示一个本地的IP地址,可以是一个物理接口、虚拟接口.
NetworkInterface ni = NetworkInterface.getByName("eth0");
URI可以由资源的名字、编号、网络位置或其他特性来标识资源。
URL可以唯一地标识一个资源在Internet上的位置。
URI语法: 模式:模式特定部分.
典型的URI由ASCII字母数字和一些特定的符号组成。所有其他字符,包括非ASCII字母数字,应当用百分号转义,其后是该字符按UTF-8编码的十六进制码;
如果没有将非ASCII字符编码为十六进制码,而是将它们直接包含在URI中,那么你得到的不是一个URI,而是IRI(国际化资源标识符);
IRI容易读写,但是很多软件和协议只支持URI.
相对URL:允许将整个文档树从一个网站移动到另一个网站,而不破坏内部链接。
可以认为缺少的各个部分都与所在文档的URL中对应的部分相同;
如果相对链接以“/”开头,那么它相对于文档根目录,而不是相对于当前文件.
java.net.URL
URL u = new URL("http://www.hao123.com");
URL u = new URL("http", "www.hao123.com", "/file")
InputStream in = u.openStream(); //不包括任何http首部或协议有关的任何其他信息
URLConnection uc = u.openConnection();
InputStream in = uc.getInputStream(); //可以读取首部
URL类的equals()方法会尝试用DNS解析主机,这是一个阻塞的IO操作;应当避免将URL存储在依赖equals()的数据结构中,如HashMap;
更好的选择是java.net.URI,可以在必要时将URI、URL来回转换.
URL类主要用于从服务器下载内容.
java.net.URI
URI对象纯粹用于解析和处理字符串,没有网络获取功能.
URI u = new URI("http://www.hao123.com");
toString()返回未编码的字符串,实际上返回的是一个IRI,利于向人们显示,但可能会接收到无效的特殊字符,通常不用于获取数据。
toASCIIString()返回URI的编码的字符串形式,一般推荐用这个获取数据.
编码:
在URL中,#号表示文件名的结束,后面是片段标识符.
空格编码为%20,或者+加号.
加好本身编码为%2B.
URLEncoder
String str = URLEncoder.encode("查询信息", "UTF-8");
URLDecoder
String str = URLDecoder.decode("信息", "UTF-8");
口令使用char数组,当不再需要口令时可以将它清除;String在清除前必须等待垃圾回收.
MIME类型分为两级:类型type和子类型subtype.
HTTP1.0会为每个请求打开一个新连接;
HTTP1.1透明地支持keep-alive,服务器不必在发送响应后就关闭连接,可以保持连接打开,在同一个socket上等待来自客户端的新请求.
HTTP方法:
GET没有副作用;
PUT有幂等性;
Delete有幂等性;
POST最通用;
Head相当于Get,不过只返回资源的首部,而不返回具体的数据;
这个方法常用于检查文件的修改日期,查看本地缓存中存储的文件副本是否有效.
OPTIONS客户端问服务器可以如何处理一个指定的资源;
TRACE回显客户端请求来进行调试.
POST请求的HTTP首部中,需要包含两个字段来指定主体的性质:
Content-length:指定主体中有多少字节;
Content-type:指定MIME媒体类型.
Cookie:
默认情况下,cookie来自哪个服务器就应用于哪个服务器;不过网站也可以指示一个cookie应用于整个子域,而不是最初的服务器.
服务器只能为它直接所属的域设置cookie.
(一些网站把一个域的一个图像或其他内容嵌入在另一个域的一个页面中,从而绕过这个限制。所嵌入内容设置的cookie,不是由页面本身设置,称为第三方cookie;一些web浏览器默认阻塞这些第三方的cookie).
cookie的作用域受路径限制,默认是最初的url和所有子目录.
为了针对cookie窃取攻击(如XSRF)提高安全性,cookie可以设置HttpOnly属性。这会告诉浏览器只通过http和https返回cookie,特别强调不能由javaScript返回.