java网络编程(二)

时间:2022-04-09 16:17:21

URLConnection是一个抽象类,它是java的协议处理器机制的一部分;运行时环境会根据所用的协议来创建所需的对象.

它存在一个问题,URLConnection与HTTP绑定过于紧密;它假定传输的每个文件前面都有一个MIME首部或类似的东西;不过,大多数经典协议如FTP、SMTP并不使用MIME首部.


URLConnection同URL的区别:

URLConnection提供了对HTTP首部的访问;

URLConnection可以在客户端配置请求参数;

URLConnection除了读取,还可以向服务器发送数据.


URL u = new URL("http://www.baidu.com");

URLConnection uc = u.openConnection();

InputStream raw = uc.getInputStream();

String contentType = uc.getContentType();

int contentLength = uc.getContentLength(); 

获取任意首部字段:public String getHeaderField(String name)


在连接打开之前可以设置URLConnection对象的属性:如doInput、dooutput、ifmodifiedSince、useCaches、超时的设置.


配置客户端请求给服务器的HTTP首部:

public void setRequestProperty(String name, String value);

public void addRequestProperty(String name, String value);


向服务器写入数据:

URLConnection在默认情况下不允许输出,所以在请求输出流之前必须调用setDoOutput(true),为一个http的url设置为true时,请求方法自动由get变为post(因为含有请求体).

uc.setDoOutput(true);

OutputStream out = uc.getOutputStream();

....

out.flush();

out.close();

不要忘记关闭流,如果流没有关闭,就不会发送任何数据.


HttpURLConnection抽象类:

使用http URL构造的URL对象并调用其openConnection()方法,返回的URLConnection其实就是HttpURLConnection的一个实例,可以强制转换.


URL u = new URL("http://www.hao123.com");

URLConnection uc = u.openConnection();

HttpURLConnection http = (HttpURLConnection)uc;


设置请求方法:public void setRequestMethod(String method) throws ProtocolException;

参数应当是GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE.(要区分大小写)

只设置请求方法通常不够,还需要调整HTTP首部,可能要提供消息体.(例如:post提交表单,要提供Content-length首部).

有些请求方法服务器不一定支持,具体的细节得看服务器.


断开与服务器的连接:disconnect()

得到响应码:public int getResponseCode() throws IOException

得到错误流:public InputStream getErrorStream()   一般地,getInputStream()失败后,会在catch块中调用getErrorSteam()



分块传输编码方式:public void setChunkedStreamingMode(int chunkLength)   //要在连接URL之前设置.

在分块传输编码方式中,请求主体以多个部分发送,每个部分都有自己单独的内容长度。

分块传输需要服务器支持,且会妨碍身份认证和重定向.



客户端Socket:java.net.Socket是java完成客户端TCP操作的基础类.

其他建立TCP网络连接的面向客户端的类,如URL、URLConnection、Applet和JEditorPane最终都会调用这个类的方法.

这个类本身使用原生代码与主机操作系统的本地TCP栈进行通信.


Socket socket = new Socket("www.hao123.com", 80);

这不只是创建这个对象,实际上它会在网络上建立连接;若连接超时,或服务器没在80端口监听,则抛出异常IOException.

socket.setSoTimeOut(15000);   //强烈建议设置超时,单位毫秒,防止连接服务器时服务器挂起;超时抛出SocketTimeoutException

InputStream in = socket.getInputStream();

OutputStream out = socket.getOutputStream();

out.flush();

socket.close();   // close()方法同时关闭socket的输入和输出.


半关闭socket:

只关闭输入流:public void shutdownInput() throws IOException

只关闭输出流:public void shutdownOutput() throws IOException

这些并不关闭socket,实际上它会调整与socket连接的流,使它认为已经到了流的末尾.

即使半关闭了流,或两半都关闭了,使用结束后仍需要关闭该socket,shutdown只影响流,并不释放socket关联的资源、占用的端口.


构造函数:

public Socket(String host, int port) throws UnknownHostException, IOException

public Socket(InetAddress host, int port) throws IOException

//选择网卡

public Socket(String host, int port, InetAddress interface, int localPort) throws UnknownHostException, IOException

public Socket(InetAddress host, int port, InetAddress interface, int localPort) throws IOException


SocketAddress类表示一个连接的端点


远程地址:public InetAddress getInetAddress()

远程端口:public int getPort()

本地地址:public InetAddress getLocalAddress()

本地端口:public int getLocalPort()

远程地址就是服务器地址;

远程端口是服务器监听的端口;

本地端口,通常是由系统在运行时从未使用的空闲端口中选择;通过这种方法,系统中多个不同的客户端就可以同时访问相同的服务了。

客户端的本地端口与本地主机的IP一同嵌入在出站IP包中,所以服务器可以正确的向客户端相应的端口发回数据.


对缓冲区的设置:

将缓冲区大小设置的过高,程序会试图以过高的速度收发数据,而网络来不及处理,就会导致拥塞、丢包和下降.



服务器socket: ServerSocket

服务器Socket监听TCP端口等待连接,而客户端Socket发起连接;一旦ServerSocket建立了连接,服务器会创建一个常规的Socket对象传输数据.


ServerSocket server = new ServerSocket(13);  //服务器监听13端口

Socket  socket = server.accept();   //accept()是一个阻塞方法,等待客户端请求

OutputStream out = socket.getOutputStream();

...

out.flush();

socket.close();

server.close();


操作系统将把指向某个特定端口的入站连接请求存储在一个先进先出的队列中。java服务器socket队列长度将是操作系统所允许的最大值(小于等于50);

队列中未处理连接达到最大时,主机会拒绝这个端口上的额外连接,直到队列腾出位置,所以服务器要采用多线程,一般使用固定的线程池.



安全Socket:

JSSE java安全Socket扩展可以使用SSL3和TLS(传输层安全)协议及算法保证安全.

对称密钥不安全;一般使用非对称密钥(公钥、私钥),但是无法防范中间人攻击.


SocketFactory factory = SSLSocketFactory.getDefault();

Socket socket = factory.createSocket("www.hao123.com", 80);  //本地是客户端,要连接到服务器

获得流

设置密码组  socket.setEnabledCipherSuites(密码组);

刷新

关闭


密码组通常用TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256、AES_256_CBC_SHA256

JSSE会在一个会话里重用密钥;



安全服务器Socket:SSLServerSocket

1,使用keytool生成公开密钥和证书

2,花钱请可信任第三方认证你的证书

3,为你使用的算法创建一个SSLContext

4,为你要使用的证书源创建一个TrustManagerFactory

5,为你要使用的密钥类型创建一个KeyManagerFactory

6,为密钥和证书数据库创建一个KeyStore对象

7,用密钥和证书填充KeyStore对象

8,用KeyStore及其口令短语初始化KeyManagerFactory

9,用KeyManagerFactory中的密钥管理器(必要)、TrustManagerFactory中的信任管理器和一个随机源来初始化上下文.(若接受默认值的话,这俩都设null)