zoukankan      html  css  js  c++  java
  • 网络编程梳理:Android网络基础知识复习

    本博客为原创 http://www.cnblogs.com/wondertwo/p/5744872.html 未经许可不得转载


    0x00 Http请求及其含义

    • GET:请求获取Request-URI所标识的资源;
    • POST:在Request-URI所标识的资源后附加新数据;
    • PUT:请求服务器存储一个资源,并用Request-URI作为其标识;
    • DELETE:请求服务器删除Request-URI标识的资源;
    • OPTIONS:请求查询服务器的性能,或者查询与资源相关的选项和需求;
    • HEAD:请求获取由Request-URI所标识的资源的响应消息头;
    • TEACE:请求服务器回送收到的请求消息,主要用于测试和诊断;
    • CONNECT:保留关键字,将来使用;

    0x01 TCP/IP 4层模型

    • 应用层:在应用层中,数据以应用内部使用的格式进行传送,然后被编码成标准协议的格式,比如万维网的HTTP协议、接收电子邮件使用的POP3和IMAP协议、发送邮件使用的SMTP协议、文件传输使用的FTP协议,以及远程登录使用的SSH和Telnet等。所以用户通常至于应用层进行交互;
    • 传输层:响应来自应用层的服务请求,并向网络层发出服务请求。传输层提供两台主机之间透明的数据传输,通常用于端到端连接、流量控制或错误恢复。这层最重要的两个协议是TCP(Transmission Control Protocol,传输控制协议)和UDP(User Datagram protocol,用户数据报协议);
    • 网络层:网络层提供端到端的数据包交付,负责数据包从源发送到目的地,任务包括网络路由,差错控制,IP编址等。这层包括的重要协议有:IP(IPv4,IPv6)、ICMP(Internet Message Control,Internet控制报文协议)、IPSec(Internet Protocol Security,Internet协议安全);
    • 网络接口层:负责通过主机发送和接收IP数据报;允许主机连入网络时使用多种现成流行的技术,比如以太网、令牌网、帧中继、ATM、X.25、DDN、SDH、WDM等。

    下图是传统七层模型与TCP四层模型的对比

    一个工程应用一般都会使用到两个传输层协议之一:面向连接的TCP传输控制协议和面向无连接的UDP用户数据报协议。

    TCP协议

    传输控制协议(Transmission Control Protocol, TCP),是一种面向连接的、可靠地、基于字节流的传输层通信协议。在保证可靠性的基础上,采用超时重传和稍待确认机制,在酒量控制上,采用滑动窗口协议,协议中规定,对于窗口内未经确认的分组需要重传;在拥塞控制上,采用慢启动算法。原理如下图:

    TCP和UDP的区别

    TCP和UDP在传输过程冲的具体实现方法不同,两者都接收传输协议数据包并将其内容向前传输到应用层。TCP把消息分解成数据包,并在接收端以正确的顺序把他们重新装配起来,TCP还处理对遗失数据包的重传请求,位于上层的应用层要处理的事情就少多了。UDP不提供装配和重传请求这些功能,它只是向前喜欢送数据包。位于上层的应用层必须确保消息是完整的。并且是以正确的顺序装配的。


    0x02 Socket套接字

    一台服务器可能会提供多种服务,每服务都对应一个Socket(可以吧Socket理解为一个插座,客户需要哪种服务,就把插头插到服务对应的插座上);用户的插头也是一个Socket。Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。Socket把复杂的TCP/IP协议隐藏在Socket接口后面,对用户来说,一组简单的Socket接口就是全部,Socket会组织数据,已符合指定的协议。Socket用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过套接字向网络发出请求或者应答网络的请求。Socket的基本操作包括:

    • 连接远程机;
    • 发送数据;
    • 接收数据;
    • 关闭连接;
    • 绑定端口;
    • 监听到大数据;
    • 在绑定的端口上接受来自远程机器的连接;

    java.net 包下提供了 ServerSocket 和 Socket 两个类,前者用于客户端可以实现连接远程服务器,发送数据,接收数据,关闭连接等,服务器端Socket还要实现绑定端口,监听到达数据,接收来自远程机器的连接。

    客户端 Socket 有如下几个构造方法

    有如下几个成员方法

    • public InputStream getInputStream():读出该Socket数据
    • public OutputStream getOutputStream():向该Socket写入数据
    • public synchronized void close():关闭该Socket

    服务端 ServerSocket 的构造方法如下:

    有如下几个重要的重要的成员方法

    构造完ServerSocket之后,需要调用ServerSocket.accept()方法来等待客户端的请求(因为Socket是绑定在端口上面的,所以知道是哪个客户端请求的),accept()方法会返回请求这个服务的客户端的Socket实例,然后调用这个Socket实例的相应的方法,操作传输过来的数据信息,当这个Socket实例操作完毕后,调用close()方法将其关闭。


    0x03 TCP的C/S通信模型

    TCP服务端工作步骤如下:

    1. 调用ServerSocket(int port) 创建一个ServerSocket,并绑定到指定端口上;
    2. 调用accept()方法监听连接请求,如果客户端请求连接,则接受连接并返回通信套接字Socket;
    3. 调用Socket类的getOutputStream()和getInoputStream()方法获取输入流和输出流,开始网络数据的发送和接收;
    4. 关闭通信Socket;

    // 创建一个ServerSocket对象
    ServerSocket serverSocket = null;
    try {
    	// TCP_SERVICE_PORT为指定端口号,为int类型
    	serverSocket = new ServerSocket(TCP_SERVICE_PORT);
    	// 监听连接请求
    	Socket socket = serverSocket.accept();
    	// 开始读写
    	BufferedReader in = new BufferedReader(new InputStream(socket.getInputStream()));
    	BufferedWriter out = new BufferedWriter(new OutputStream(socket.getOutputStream()));
    	// 读取接收信息,转换为字符串
    	String incomingMsg = in.readLine() + System.getProperty("line.separator");
    	// 生成发送字符串
    	String outgoingMsg = "goodbye from port " + TCP_SERVICE_PORT + System.getProperty("line.separator");
    	out.write(outgoingMsg);
    	// 刷新发送
    	out.flush();
    	// 关闭
    	socket.close();
    } catch (InterruptedIOException e) { // 超时异常
    	e.printStackTrace();
    } catch (IOException e) { // IO异常
    	e.printStackTrace();
    } finally {
    	if (serverSocket != null) {
    		try {
    			serverSocket.close();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    TCP客户端工作步骤如下:

    1. 调用Socket()创建一个流套接字,并连接到服务器;
    2. 调用Socket类的getOutputStream()方法和getInputStream()方法获取输出和输入流,开始网络数据的发送和接收;
    3. 关闭通信套接字;

    try {
    	// 初始化Socket,TCP_SERVICE_PORT为指定端口号,为int类型
    	Socket socket = new Socket(TCP_SERVICE_PORT);
    	// 生成输出流
    	BuffereedReader in = new BufferedReader(new InputStream(socket.getInputStream()));
    	BufferedWriter out = new BufferedWriter(new OutputStream(socket.getOutputStream()));
    	// 读取接收信息,转换为字符串
    	String incomingMsg = in.readLine() + System.getProperty("line.separator");
    	// 生成发送字符串
    	String outMsg = "TCP connected to " + TCP_SERVICE_PORT + System.getProperty("line.separator");
    	out.write(outMsg);
    	// 刷新发送
    	out.flush();
    	// 获取输入流
    	String inMsg = in.readLine() + System.getProperty("line.separator");
    	// 关闭连接
    	socket.close();
    } catch (UnknownHostException e) { // 超时异常
    	e.printStackTrace();
    } catch (IOException e) { // IO异常
    	e.printStackTrace();
    }
    

    以上步骤需要注意

    1. 无论是客户端还是服务端,都要添加 UnknownHostException,来处理网络异常;添加 IOException 来处IO异常;
    2. 需要在Android客户端清单文件中添加网络权限:

    <uses-permision android:name="android.permission.INTERNET" />
    

    0x04 关于Apache HttpClient

    简单来说,Apache HttpClient就是一个增强版的HttpURLConnection,HttpURLConnection的所有功能都能实现,不同点是它更加关注于如何发送请求、接收响应、以及管理HTTP连接。使用HttpClient发送请求、接收响应很简单,只需如下几步:

    • 创建HttpClient对象;
    • 如果需要发送GET请求,则创建HttpGet对象,如果需要发送POST请求,则常见HttpPost对象;
    • 如果需要发送请求参数,则可调用HttpGet、HttpPost共同的setParams(HttpParams params)方法来添加请求参数;对于HttPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数;
    • 调用HttpClient对象的excute(HttpUriReuest request)等方法发送请求,执行该方法返回一个HttpResponse;
    • 抵用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可以获取服务器的响应头;调用HttpResponse的getEntity()方法可以获取HttpEntity对象,该对象包装了服务器的响应内容,程序可通过该对象获取服务器的响应内容;

    在Android6.0+谷歌官方api移除了对HttpClient的支持,如果要使用HttpClient,可在moudle的build.gradle文件中添加如下库依赖即可:

    android {
    	...
    	useLibrary 'org.apache.http.legacy'
    }
    

    URLConnection访问网络

    在很多情况下,需要保存用户浏览过的网络页面,实现这个功能:通过网址生成URL对象,然后打开链接,写入buffer,最后写入字符串中。实现代码如下:

    try {
    	URL newUrl = new URL("http://translate.google.com");
    	URLConnection connect = newUrl.openConnection();
    	DataInputStream dis = new DataInputStream(connect.getInputStream());
    	BufferedReader in = new BufferedReader(new InputStream(dis, "UTF-8"));
    	String html = "";
    	String readLine = null;
    	while ((readLine = in.readLine()) != null) {
    		html = html + readLine;
    		Log.d("OpenWebviewActivity", readLine);
    	}
    	in.close();
    } catch (MalformedURLException me) {
    } catch (IOException ioe) {
    }
  • 相关阅读:
    perl 判断网站内容是否变更
    鸿雁电器oa系统中决策支持模块效果
    爬虫1-15
    自动封杀脚本
    图表中如何实现动态变更分类轴与系列值
    错误代码: 1305 PROCEDURE world.insert_data does not exist
    错误代码: 1054 Unknown column 't.createUsrId' in 'group statement'
    错误代码: 1247 Reference 'startTime' not supported (forward reference in item list)
    Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Query was empty
    echarts中地图提示"TypeError:i is undefined"
  • 原文地址:https://www.cnblogs.com/wondertwo/p/5744872.html
Copyright © 2011-2022 走看看