Socket和Http是Android常用的两种通信方式,但是两者又是有所不同的,使用场景有所不同,这篇文章就来总结总结这两种方式。
首先,Socket是什么呢?其实Socket就是一组接口而已,其实计算机网络中通常会把通讯网络分为5层模型:
Socket就是运输层和应用层中间的抽象层,隐藏了TCP/IP协议簇(位于运输层)的具体实现,所以位于应用层的应用想要和底层的运输层通信,直接调用Socket就行了。Socket的类型其实有两种,一种是TCP应用服务,一种是UDP应用服务,有啥区别呢?
| TCP | UDP
----|-------|------
是否连接| 面向连接| 面向非连接
传输可靠性|可靠的| 不可靠的
应用场合|传输大量的数据|少量数据
速度|慢|快
其实在Android中除了视频音频等对丢包率要求不高的情况,其它时候还是建议用TCP的。Socket不仅可以用于网络通信,还可以用于应用的跨进程通信。Socket的使用方式也很简单。
public void startTcpSocketConnect(){
new Thread(new Runnable() {
@Override
public void run() {
try {
mSocket = new Socket(serverIp, serverPort);
in = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
mSocket.getOutputStream())), true);
while (true) {
if (mSocket.isConnected()) {
if (!mSocket.isInputShutdown()) {
if ((content = in.readLine()) != null) {
content += "\n";
if (mTcpSocketListener != null)
mTcpSocketListener.callBackContent(content);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
都是几乎固定的写法,没什么稀奇的,网上一搜一堆代码。
当然UDP的话就是
socket = new DatagramSocket(1985);
....
DatagramPacket packet = new DatagramPacket(data, data.length ,serverAddress ,10025);
socket.send(packet);//把数据发送到服务端。
socket.receive(packet); //接收数据
再说Http,Http是建立在请求/响应模型上的应用层协议,客户端首先建立一条与服务器的TCP连接并发送一个请求,然后服务器作出相应的响应。其中HTTP/1.0用的是短链接,没发送一次请求就会新建立一个连接,而每一个连接都要3次握手,这是很耗费资源的,于是HTTP/1.1做出来改进,使用了长连接,只建立一个TCP连接重复使用其传输一些列的请求/响应。这样就节省了这种开销了。
题外话,如果有一种协议即能像UDP那样高效又能像TCP那样的可靠就好了,哈哈,不过听说有人已经在研究UDP和TCP混合的HTTP了,不知道是不是真的。
既然Http是基于TCP之上的,那么可不可以用Socket来实现下Http呢?答案当然是可以的。
static void get(String url) throws IOException {
String host = new URL("http://" + url).getHost();
String path = url.substring(host.length());
InetSocketAddress address = new InetSocketAddress(host, 80);
Socket socket = new Socket();
socket.connect(address);
OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream());
BufferedWriter bufferedWriter = new BufferedWriter(streamWriter);
bufferedWriter.write("GET " + path + " HTTP/1.1\r\n");
bufferedWriter.write("Host: " + host + "\r\n");
bufferedWriter.write("Content-Type: application/x-www-form-urlencoded\r\n");
bufferedWriter.write("\r\n");
bufferedWriter.flush();
BufferedInputStream inputStream = new BufferedInputStream(socket.getInputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
String line;
while ((line = bufferedReader.readLine()) != null) {
Log.d("1234", line);
}
bufferedReader.close();
bufferedWriter.close();
socket.close();
}```
这里只是实现了get方法,其实post方法也是一样的原理的请求头最好加上“Content-Length”和“Content-Type”,另外需要注意的是传输的数据最好编码一下,以免出现乱码或编码错误。