【Java学习】网络连接:Socket、HTTP - Go语言中文社区

【Java学习】网络连接:Socket、HTTP


1,Socket(套接字)

1)流式套接字(对应TCP)

2)用户数据报套接字(对应UDP)

3)常用方法

①ServerSocket(int port)

是服务端绑定port端口,调accept()监听等待客户端连接,它返回一个连接队列中的一个socket。

②Socket(InetAddress address , int port)

创建客户端连接主机的socket流,其中InetAddress是用来记录主机的类,port指定端口。
socket和servletSocket的交互如下图所示:
socket和servletSocket的交互

2,HTTP

Android中主要提供了两种方式来进行HTTP操作,HttpURLConnection和HttpClient。这两种方式都支持HTTPS协议、以流的形式进行上传和下载、配置超时时间、IPv6、以及连接池等功能。

1)HttpURLConnection

获取HttpURLConnection的实例:

URL url = new URL("http://www.baidu.com");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();

设置一下HTTP请求所使用的方法,常用的方法主要有两个GET和POST,GET表示希望从服务器那里获取数据,而POST则表示希望提交数据给服务器:

connection.setRequestMethod("GET");

网络定制:比如设置链接超时,读取超时的毫秒数,以及服务器希望得到的一些消息头等。

connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);

调用getInputStream()方法获取到服务器返回的输入流:

InputStream in = connection.getInputStream();

调用disconnect()方法可以将HTTP链接关闭:

connection.disconnect();

流的读取:

reader = new BufferedReader(new InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null){
     response.append(line);
}
showResponse(response.toString());
//reader.close();记得最后关闭

2)HttpClient方式(过时)

包含HttpGet和HttpPost类。Android6.0开始过时,官方推荐HttpURLConnection。

①概念

HttpClient是Apache开源组织提供的HTTP网络访问接口(一个开源的项目),是一个简单的HTTP客户端(并不是浏览器),可以发送HTTP请求,接受HTTP响应。但是不会缓存服务器的响应,不能执行HTTP页面中签入嵌入的JS代码,自然也不会对页面内容进行任何解析、处理,这些都是需要开发人员来完成的。
现在Android已经成功集成了HttpClient,所以开发人员在Android项目中可以直接使用HttpClient来想Web站点提交请求以及接受响应,如果使用其他的Java项目,需要引入进相应的Jar包。

HttpClient其实是一个interface类型,HttpClient封装了对象需要执行的Http请求、身份验证、连接管理和其它特性。既然HttpClient是一个接口,因此无法创建它的实例。从文档上看,HttpClient有三个已知的实现类分别是:AbstractHttpClient, AndroidHttpClient, DefaultHttpClient,会发现有一个专门为Android应用准备的实现类AndroidHttpClient,当然使用常规的DefaultHttpClient也可以实现功能。
从两个类包所有在位置就可以看出区别,AndroidHttpClient定义在android.net.http.AndroidHttpClient包下,属于Android原生的http访问,而DefaultHttpClient定义在org.apache.http.impl.client.DefaultHttpClient包下,属于对apche项目的支持。而AndroidHttpClient没有公开的构造函数,只能通过静态方法newInstance()方法来获得AndroidHttpClient对象。

②实现

i>创建代表客户端的HttpClient对象。HttpClient client
ii>创建代表请求的对象。

HttpGet get,HttpPost post

注:对于发送请求的参数,GET和POST使用的方式不同,GET方式可以使用拼接字符串的方式,把参数拼接在URL结尾;POST方式需要使用setEntity(HttpEntity entity)方法来设置请求参数。
iii>调用HttpClient对象的execute(HttpUriRequest request)发送请求,执行该方法后,将获得服务器返回的HttpResponse对象。服务器发还给我们的数据就在这个HttpResponse相应当中。

HttpResponse response = client.execute(post)
HttpEntity entity = response.getEntity()

得到数据流:

InputStream inputStream = entity.getContent();

最后关闭过期连接。
iv>检查相应状态是否正常。服务器发给客户端的相应,有一个相应码:相应码为200,正常;相应码为404,客户端错误;相应码为505,服务器端错误。
v>获得相应对象当中的数据

③Get和Post区别

GET是从服务器上获取数据,POST是向服务器传送数据。
在客户端,GET方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放在HTML HEADER内提交。
对于GET方式,服务器端用Request.QueryString获取变量的值,对于POST方式,服务器用Request.Form获取提交的数据。
GET方式提交的数据不能大于2KB(主要是URL长度限制),而POST则没有此限制。
安全性问题。正如2中提到,使用GET的时候,参数会显示在地址栏上,而POST不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用GET;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用POST为好。

④返回数据格式

1、以HTML代码内容返回。
2、以XML字符串的形式返回,在以后的android开发中这种形式返回数据比较多。
3、以JSON对象形式返回,在网络流量上考虑JSON要比XML方式要好一些,便于解析。
在Android当中,一般使用xml和Json数据解析。

3)OkHttp

网络请求框架,可通过第三方依赖导入。
包括Get 请求、Post 请求、上传下载文件、上传下载图片等功能。

4)Volley

网络请求框架,可通过第三方依赖导入。

3,注意

1)android网络连接—主线程连接错误

无论是socket连接还是http连接,不应该在主线程中进行,否则会报错:android.os.NetworkOnMainThreadException。
正确的做法是:在异步任务或者新开子线程用于连接。

4,应用

1)检查当前网络是否可用

public class NetWork {

    /**
     * 检查当前网络是否可用
     *
     * @param context
     * @return
     */

    public static boolean isNetWork(Context context) {

        if (context != null) {
            ConnectivityManager mConnectivityManager = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
            if (mNetworkInfo != null) {
                return mNetworkInfo.isAvailable();
            }
        }
        return false;
    }
}

2)ping不同的网络并返回网络状态

public class PingIpAddr {

	/**
	 * ping网络,ping通返回true,不通返回false
	 * @param ipAddress = "74.125.47.104"
	 * @return
	 */
	public static final boolean pingIpAddr(String ipAddress) {

		try {
			/**-c 是指ping的次数 3是指ping 3次 ,-w 100 以秒为单位指定超时间隔,是指超时时间为100秒*/
			if (null == ipAddress || ipAddress.equals("")) {
				return false;
			}
			Process p = Runtime.getRuntime().exec("ping -c 1 -w 3 " + ipAddress);
			
			if (null != p) {

				int status = p.waitFor();
				if (0 == status) {
					return true;
				} 
			}
		} catch (IOException e) {

			LogUtil.i("Log", "PingIpAddr->Fail: IOException->" + e.getMessage());

		} catch (InterruptedException e) {
			LogUtil.i("Log", "PingIpAddr->Fail: InterruptedException->" + e.getMessage());
		}
		return false;
	}
}

5,网络接口

1)java.net.*(标准Java接口)

提供与联网有关的类,包括流、数据包套接字(socket)、Internet协议、常见Http处理等。比如:创建URL,以及URLConnection/HttpURLConnection对象、设置链接参数、链接到服务器、向服务器写数据、从服务器读取数据等通信。这些在Java网络编程中均有涉及,我们看一个简单的socket编程,实现服务器回发客户端信息。

2)Org.apache接口

是一个开源项目,功能更加完善,为客户端的Http编程提供高效、最新、功能丰富的工具包支持。

3)Android.net.*(Android网络接口

常常使用此包下的类进行Android特有的网络编程,如:访问WiFi,访问Android联网信息,邮件等功能。

6,HTTP与HTTPS

1)区别

http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。http的连接很简单,是无状态的。HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。
HTTPS是一种通过计算机网络进行安全通信的传输协议。HTTPS经由HTTP进行通信,但利用SSL/TLS来加密数据包。HTTPS开发的主要目的,是提供对网站服务器的身份 认证,保护交换数据的隐私与完整性。

SSL(安全套接层,secure sockets layer)
TLS(传输层安全,transport layer security),是SSL的继任者。
安全层其实就是在明文的上层和TCP层之间加上一层加密,这样就保证上层信息传输的安全。

这里写图片描述
注:TLS是SSL的升级替代版,具体发展历史可以参考传输层安全性协议。

HTTP与HTTPS在写法上的区别也是前缀的不同,客户端处理的方式也不同,具体说来:
如果URL的协议是HTTP,则客户端会打开一条到服务端端口80(默认)的连接,并向其发送老的HTTP请求。
如果URL的协议是HTTPS,则客户端会打开一条到服务端端口443(默认)的连接,然后与服务器握手,以二进制格式与服务器交换一些SSL的安全参数,附上加密的 HTTP请求。

所以HTTPS比HTTP多了一层与SSL的连接,这也就是客户端与服务端SSL握手的过程,整个过程主要完成以下工作:

  • 交换协议版本号
  • 选择一个两端都了解的密码
  • 对两端的身份进行认证
  • 生成临时的会话密钥,以便加密信道。
    SSL握手是一个相对比较复杂的过程,更多关于SSL握手的过程细节可以参考TLS/SSL握手过程

SSL/TSL的常见开源实现是OpenSSL,OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连接者的身份。这个包广泛被应用在互联网的网页服务器上。 更多源于OpenSSL的技术细节可以参考OpenSSL。

2)HTTP缓存

HTTP的缓存机制也是依赖于请求和响应header里的参数类实现的,最终响应式从缓存中去,还是从服务端重新拉取,HTTP的缓存机制的流程如下所示:
这里写图片描述
HTTP的缓存可以分为两种:
①强制缓存
需要服务端参与判断是否继续使用缓存,当客户端第一次请求数据是,服务端返回了缓存的过期时间(Expires与Cache-Control),没有过期就可以继续使用缓存,否则则不适用,无需再向服务端询问。
②对比缓存
需要服务端参与判断是否继续使用缓存,当客户端第一次请求数据时,服务端会将缓存标识(Last-Modified/If-Modified-Since与Etag/If-None-Match)与数据一起返回给客户端,客户端将两者都备份到缓存中 ,再次请求数据时,客户端将上次备份的缓存 标识发送给服务端,服务端根据缓存标识进行判断,如果返回304,则表示通知客户端可以继续使用缓存。
强制缓存优先于对比缓存。
上面提到强制缓存使用的的两个标识:

  • Expires
    Expires的值为服务端返回的到期时间,即下一次请求时,请求时间小于服务端返回的到期时间,直接使用缓存数据。到期时间是服务端生成的,客户端和服务端的时间可能有误差。
  • Cache-Control
    Expires有个时间校验的问题,所有HTTP1.1采用Cache-Control替代Expires。
    Cache-Control的取值有以下几种:

private: 客户端可以缓存。
public: 客户端和代理服务器都可缓存。
max-age=xxx: 缓存的内容将在 xxx 秒后失效
no-cache: 需要使用对比缓存来验证缓存数据。
no-store: 所有内容都不会缓存,强制缓存,对比缓存都不会触发。
我们再来看看对比缓存的两个标识:

  • Last-Modified/If-Modified-Since
    Last-Modified 表示资源上次修改的时间。
    当客户端发送第一次请求时,服务端返回资源上次修改的时间:
    Last-Modified: Tue, 12 Jan 2016 09:31:27 GMT
    客户端再次发送,会在header里携带If-Modified-Since。将上次服务端返回的资源时间上传给服务端。

If-Modified-Since: Tue, 12 Jan 2016 09:31:27 GMT
服务端接收到客户端发来的资源修改时间,与自己当前的资源修改时间进行对比,如果自己的资源修改时间大于客户端发来的资源修改时间,则说明资源做过修改, 则返回200表示需要重新请求资源,否则返回304表示资源没有被修改,可以继续使用缓存。

上面是一种时间戳标记资源是否修改的方法,还有一种资源标识码ETag的方式来标记是否修改,如果标识码发生改变,则说明资源已经被修改,ETag优先级高于Last-Modified。

  • Etag/If-None-Match
    ETag是资源文件的一种标识码,当客户端发送第一次请求时,服务端会返回当前资源的标识码:
    ETag: “5694c7ef-24dc”
    客户端再次发送,会在header里携带上次服务端返回的资源标识码:

If-None-Match:“5694c7ef-24dc”
服务端接收到客户端发来的资源标识码,则会与自己当前的资源吗进行比较,如果不同,则说明资源已经被修改,则返回200,如果相同则说明资源没有被修改,返回 304,客户端可以继续使用缓存。

3)HTTPS是如何保证安全的,证书如何校验?

4)HTTP如何实现长连接?

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/SunshineTan/article/details/79524807
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢