banner
NEWS LETTER

Android中Socket使用入门

Scroll down

前言

  • Socket的使用在 Android网络编程中非常重要
  • 今天我将带大家全面了解 Socket 及 其使用方法

1. Socket定义

  • 即套接字,是应用层 与 TCP/IP 协议族通信的中间软件抽象层,表现为一个封装了 TCP / IP协议族 的编程接口(API)

  1. Socket不是一种协议,而是一个编程调用接口(API),属于传输层(主要解决数据如何在网络中传输)
  2. 即:通过Socket,我们才能在Andorid平台上通过 TCP/IP协议进行开发
  3. 对用户来说,只需调用Socket去组织数据,以符合指定的协议,即可通信
  • 成对出现,一对套接字:
1
2
Socket ={(IP地址1:PORT端口号),(IP地址2:PORT端口号)}

  • 一个 Socket 实例 唯一代表一个主机上的一个应用程序的通信链路

2. 建立Socket连接过程

3. 原理

Socket的使用类型主要有两种:

  • 流套接字(streamsocket) :基于 TCP协议,采用 流的方式 提供可靠的字节流服务
  • 数据报套接字(datagramsocket):基于 UDP协议,采用 数据报文 提供数据打包发送的服务

具体原理图如下:

4. Socket 与 Http 对比

  • Socket属于传输层,因为 TCP / IP协议属于传输层,解决的是数据如何在网络中传输的问题
  • HTTP协议 属于 应用层,解决的是如何包装数据

由于二者不属于同一层面,所以本来是没有可比性的。但随着发展,默认的Http里封装了下面几层的使用,所以才会出现Socket & HTTP协议的对比:(主要是工作方式的不同):

  • Http:采用 请求—响应 方式。

    1. 即建立网络连接后,当 客户端 向 服务器 发送请求后,服务器端才能向客户端返回数据。
    2. 可理解为:是客户端有需要才进行通信
  • Socket:采用 服务器主动发送数据 的方式

    1. 即建立网络连接后,服务器可主动发送消息给客户端,而不需要由客户端向服务器发送请求
    2. 可理解为:是服务器端有需要才进行通信

5. 使用步骤

  • Socket可基于TCP或者UDP协议,但TCP更加常用
  • 所以下面的使用步骤 & 实例的Socket将基于TCP协议
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 
// 步骤1:创建客户端 & 服务器的连接

// 创建Socket对象 & 指定服务端的IP及端口号
Socket socket = new Socket("192.168.1.32", 1989);

// 判断客户端和服务器是否连接成功
socket.isConnected());


// 步骤2:客户端 & 服务器 通信
// 通信包括:客户端 接收服务器的数据 & 发送数据 到 服务器

<-- 操作1:接收服务器的数据 -->

// 步骤1:创建输入流对象InputStream
InputStream is = socket.getInputStream()

// 步骤2:创建输入流读取器对象 并传入输入流对象
// 该对象作用:获取服务器返回的数据
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);

// 步骤3:通过输入流读取器对象 接收服务器发送过来的数据
br.readLine();


<-- 操作2:发送数据 到 服务器 -->

// 步骤1:从Socket 获得输出流对象OutputStream
// 该对象作用:发送数据
OutputStream outputStream = socket.getOutputStream();

// 步骤2:写入需要发送的数据到输出流对象中
outputStream.write(("Carson_Ho"+"\n").getBytes("utf-8"));
// 特别注意:数据的结尾加上换行符才可让服务器端的readline()停止阻塞

// 步骤3:发送数据到服务端
outputStream.flush();


// 步骤3:断开客户端 & 服务器 连接

os.close();
// 断开 客户端发送到服务器 的连接,即关闭输出流对象OutputStream

br.close();
// 断开 服务器发送到客户端 的连接,即关闭输入流读取器对象BufferedReader

socket.close();
// 最终关闭整个Socket连接

具体实例

1. 客户端 实现

步骤1:加入网络权限

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

步骤2:主布局界面设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<Button
android:id="@+id/connect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="connect"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/disconnect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="disconnect"
app:layout_constraintTop_toBottomOf="@+id/connect" />

<TextView
android:id="@+id/receive_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/disconnect" />

<Button
android:id="@+id/Receive"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Receive from message"
app:layout_constraintTop_toBottomOf="@id/receive_message" />

<EditText
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/Receive" />

<Button
android:id="@+id/send"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="send"
app:layout_constraintTop_toBottomOf="@id/edit" />
</androidx.constraintlayout.widget.ConstraintLayout>

步骤3:创建Socket连接、客户端 & 服务器通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
class SocketActivity : BaseActivity() {

/**
* 主 变量
*/

// 主线程Handler
// 用于将从服务器获取的消息显示出来
private lateinit var mMainHandler: Handler

// Socket变量
private lateinit var socket: Socket

// 线程池
// 为了方便展示,此处直接采用线程池进行线程管理,而没有一个个开线程
private lateinit var mThreadPoolExecutor: ExecutorService

/**
* 接收服务器消息 变量
*/
// 输入流对象
lateinit var inputS: InputStream

// 输入流读取器对象
lateinit var inputStreamReader: InputStreamReader
lateinit var bufferedReader: BufferedReader

// 接收服务器发送过来的消息
lateinit var response: String

/**
* 发送消息到服务器 变量
*/
// 输出流对象
lateinit var outputStream: OutputStream
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_socket)
// 初始化线程池
mThreadPoolExecutor = Executors.newCachedThreadPool()
// 实例化主线程,用于更新接收过来的消息
mMainHandler = object : Handler(Looper.myLooper()!!) {
override fun handleMessage(msg: Message) {
when (msg.what) {
0 -> receive_message.text = response
}
}
}
/**
* 创建客户端 & 服务器的连接
*/
connect.setOnClickListener {
// 利用线程池直接开启一个线程 & 执行该线程
mThreadPoolExecutor.execute {
// 创建Socket对象 & 指定服务端的IP 及 端口号
socket = Socket("47.94.228.228", 8989)
// 判断客户端和服务器是否连接成功
Toast.makeText(this, "" + socket.isConnected, Toast.LENGTH_SHORT).show()
}
}

/**
* 接收 服务器消息
*/
Receive.setOnClickListener {
mThreadPoolExecutor.execute {
inputS = socket.getInputStream()
inputStreamReader = InputStreamReader(inputS)
bufferedReader = BufferedReader(inputStreamReader)
response = bufferedReader.readLine()
val msg = Message.obtain()
msg.what = 0
mMainHandler.sendMessage(msg)
}
}
/**
* 发送消息 给 服务器
*/
send.setOnClickListener {
mThreadPoolExecutor.execute {
outputStream = socket.getOutputStream()
outputStream.write((edit.text.toString() + "\n").toByteArray(Charset.forName("utf-8")))
outputStream.flush()
}
}
/**
* 断开客户端 & 服务器的连接
*/
disconnect.setOnClickListener {
outputStream.close()
bufferedReader.close()
socket.close()
Toast.makeText(this, "" + socket.isConnected, Toast.LENGTH_SHORT).show()
}

}
}
其他文章
目录导航 置顶
  1. 1. 前言
    1. 1.1. 1. Socket定义
    2. 1.2. 2. 建立Socket连接过程
    3. 1.3. 3. 原理
    4. 1.4. 4. Socket 与 Http 对比
    5. 1.5. 5. 使用步骤
  2. 2. 具体实例
    1. 2.1. 1. 客户端 实现
请输入关键词进行搜索