Java(1.8)高级特性-网络

2019-03-31  本文已影响0人  czn5991

网络编程涉及到了最基础的Socket编程,以及基于次的网络服务。下面将介绍在Java中如何实现Socket以及一些简单的网络客户端和服务端。

Socket

  1. 连接
    Socket类是Java中实现的基本的网络编程类,可以通过地址和端口来进行初始化,连接到该服务器的端口上,也可以使用无参构造函数,再调用connect()方法连接上服务器。两者的区别是当直接使用带参构造函数去初始化Socket时,进程会一直阻塞直到连接上服务器,而如果是在使用无参构造函数创建Socket后调用connect()方法,可以设置连接的时间限制,当超过时间后就会抛出IOException
Socket s1=new  Socket(String host,int port);
Socket s2=new Socket();
s2.connect(host,port,1000);//时限为1秒钟
  1. 通信
    Socket对象连接上服务器后,就可以通过socket.getInputStream()socket.getOutputStream()与服务器进行数据传输。这两个方法返回的是(In|Out)putStream对象,可以使用输入输出流的处理方法来进行读写。最后通过socket.close()来关闭。
  2. 其余方法
    此外,Socket类还实现了一些有助于平常使用的方法。
public InetAddress getInetAddress();//获取socket连接的服务器地址
public int getPort();//获取socket连接的服务器端口
public InetAddress getLocalAddress();//获取socket连接的本地的地址
public int getLocalPort();
public boolean isClosed();
...

ServerSocket

  1. 创建
    服务器程序会在某个端口等待用户程序的连接,在创建ServerSocket的时候,可以进行端口指定。
    创建完ServerSocket对象后,通过调用s.accept()方法来等待用户程序连接上服务器。该方法阻塞进程直到用户连接,并返回一个Socket对象。获取到Socket对象后就可以通过输入输出流向用户程序进行读写。
ServerSocket ss=new ServerSocket(port);
Socket s=ss.accept();
InputStream in=s.getInputStream();
OutputStream out=s.getOutputStream();
  1. 并发处理
    当要同时处理多个用户程序连接服务器的时候,可以在获得Socket对象后创建线程来处理该Socket的读写。
while(ture){
  Socket s=ss.accept();
  Thread t=new Thread(
    public void run(){
      //input and output
    }
  );
  t.start();
}
  1. 半关闭
    Socket对象提供了只关闭输入/输出流其中之一而不断开连接的方法,即shutdown(In|Out)put(),在断开后,任何输入或输出都将会被抛弃。断开后没有办法再重新连接上,因此这种方法只适用于一站式的服务。

因特网地址

Java中提供了InetAddressInetSocketAddress类来表示因特网地址。其中InetSocketAddress类单纯地用来表示一个地址,即ip:portInetAddress用来表示一个ip,并提供了用于获得域名对应的ip等功能。

public boolean isReachable(int timeout) throws IOException;
public String getHostName();
public static InetAddress getByName(String host);
//获取一个域名所有的ip地址
public static InetAddress[] getAllByName(String host);
//获取本地的ipv4地址
public static InetAddress getLocalHost() throws UnknownHostException;
... 

获取Web服务

使用Socket只能与指定的ip:port进行通信,而无法获得服务器特定目录下的资源,即无法通过URL获得资源(?)。URI是统一资源标识符,其中能够定位到数据的称为URL(统一资源定位符),不能定位到数据的称为URN(统一资源名称)。
Java提供了URL类对URL进行访问,提供了URI类对标识符进行解析。

  1. URI
    一个URI具有这样的格式,[scheme:]schemeSpecificPart[#fragment],其中[...]表示可选的部分,并且:#可以被包含在标识符内。包含[scheme:]部分的为绝对URI,否则为相对URI,其中schemeSpecificPart/开头的绝对URI为不透明的,例如mailto:cay@test.com。所有透明的绝对URI和所有相对URI都是分层的,如https://test.com/index../../java/net/Socket.html#Socket()。一个分层的URI的schemeSpecificPart具有这样的格式,[//authority][path][?query],基于服务器的URI的authority部分具有这样的格式[user-info@]host[:port]
    URI类提供了解析标识符和处理相对(绝对)标识符的功能。其中resolve()方法提供了解析相对URI,将其生成绝对URI的方法,relativize()方法提供了相对化方法,将绝对URI生成相对URI。比如,b/chttps://a.com/b为参数调用resolve()将得到https://a.com/b/chttps://a.com/b/chttps://a.com/b为参数调用relativize()将得到c
public String getSchemeSpecificPart();
public String getAuthority();
public String getUserInfo();
public String getHost();
public int getPort();
...
  1. URL
    URL类提供了从给定url获得资源的方法。URL提供了与URI类似的解析标识符的方法,此外还可以通过调用openStream()获得InputStream对象来获取资源内容。不过URL类没有提供输出的方法,想要和服务器进一步交互,可以调用openConnection()方法来获得URLConnection对象来进一步操作。
URL url = new URL(urlString);
InputStream in = url.openStream();
  1. URLConnection
    该类提供了向服务器输出和接收服务器输入的功能。操作URLConnection需要遵循一下几个步骤:
    ⑴ 调用URLopenConnection()来获得 URLConnection对象。
    ⑵ 设置参数和请求的属性。
    ⑶ 调用connect()连接远程资源。
    ⑷ 建立连接后就可以查询头信息和访问资源数据。
public void setAllowUserInteraction();
public void setDoInput();
public void setDoOutput();
public void setIfModifiedSince();//连接只对某个特定日期以来修改过的数据感兴趣
public void setUseCaches();
//修改请求头属性
public void addRequestProperty(String key, String value);
public Object getContent();
public String getHeaderField();
public InputStream getInputStream();
public  OutputStream getOutputStream();
public String getContentEncoding();
public int getContentLength();
public String getContentType();
public long getDate();
public long getExpiration();
public long getLastModifed();
  1. 提交表单
    想服务器提交表单有Get和Post两种方法。
URL url=new URL(urlString);
URLConnection connection=url.openConnection();
connection.setDoOutput(true);
PrintWriter out=new PrintWriter(connection.getOutputStream(),"utf-8");
out.print(name1+"="+URLEncoder.encode(value1,"utf-8")+"&");
out.print(name2+"="+URLEncoder.encode(value2,"utf-8"));
out.close();
//在连接前关闭自动重定向
connection.setInstanceFollowRedirects(false);
//在发送请求之后获取相应码
int responseCode=connection.getResponseCode();
//如果是HttpURLConnection.HTTP_MOVED_PERM
//或HttpURLConnection.HTTP_MOVED_TEMP
//或HttpURLConnection.HTTP_SEE_OTHER
//就获取Location响应头,获得重定向URL,断开连接,创建到新的URL连接
String location=connection.getHeaderField("Location");
if(location!=null){
  URL base=connection.getURL();
  connection.disconnect();
  connection=(HttpURLConnection) new URL(base,location).openConnection();
}
HTTP

HTTP有0.9、1.0、1.1、2.0这几个版本。

  1. HTTP 0.9
    HTTP 0.9是第一个HTTP协议的版本,只支持GET请求,不支持请求头且没有协议头,只支持纯文本内容。该版本的协议就已经支持了无状态特性,事务结束就关闭请求,访问地址不存在也不会返回错误信息。
  2. HTTP 1.0
    HTTP 1.0在0.9的版本上支持了请求和响应头部、响应以一个响应状态行开始、响应信息不仅限于超文本、支持了POST请求。该版本默认使用了短连接,每次请求建立一个TCP连接。
  3. HTTP 1.1
    新增了keep alive、chunked编码传输、字节范围请求、请求流水线等特性。还支持了HOST域(即一个IP下可能有多个服务器,通过主机名指定)、增加了connect/trace/delete/put/options的请求方法。
  1. HTTP 2.0
    该协议是下一代HTTP协议,以下是其特性。
HTTP包结构

一个HTTP包由一下部分构成:起始行、一个或多个头域、一个空行表示头域的结束、实体消息。

GET http://download.microtool.de:80/somedata.exe
Host: download.microtool.de
Accept:*/*
Pragma: no-cache
Cache-Control: no-cache
Referer: http://download.microtool.de/
User-Agent:Mozilla/4.04[en](Win95;I;Nav)
Range:bytes=554554-

HTTP包的第一行为起始行,请求包的起始行包含请求方法、URL、HTTP版本;响应包的起始行包含HTTP-Version Status-Code Reason-PhraseHTTP-Version表示支持的HTTP版本、Status-Code表示三位数字的结果代码、Reason-Phrase对结果代码的文本描述等。
上述请求包中HostAcceptPragma就为头域,通过<key>:<value>的形式表示。
头域可以分为通用头域、请求头域、响应头域和实体头域。

上一篇 下一篇

猜你喜欢

热点阅读