我是靠谱客的博主 斯文往事,这篇文章主要介绍Android Socket连接(模拟心跳包,断线重连,发送数据等),现在分享给大家,希望可以做个参考。

  • 首页
  • 博客
  • 学院
  • 下载
  • GitChat
  • TinyMind
  • 论坛
  • 问答
  • 商城
  • VIP
  • 活动
  • 招聘
  • ITeye
  • CSTO
喻志强的博客

耐心 细心 用心 传播正能量

RSS订阅
Android Socket连接(模拟心跳包,断线重连,发送数据等)

这两天做了一个项目是app通过socket连接自动炒菜机,给炒菜机发指令,炒菜机接收到指令会执行相应的操作。(程序虽然做的差不多了,然而我连炒菜机长什么样都没见过)

其实作为一个会做饭的程序猿,我坚信还是自己动手做的饭菜比较好吃,毕竟做饭还是很有趣的。

闲话不多说,因为是通过socket去连接炒菜机的,并且要求每两秒要给炒菜机发送一个指令,点击按钮的话也要发送相应的指令。 


因为是要保证全局只能有一个连接,而且我们还需要在不同的Activity中发指令,因此肯定不能在需要发指令的界面中都去连接socket,这样一来不好管理,性能也不好,重复代码也会比较多,所以想了一下还是把socket放到service中比较好,发指令功能都放在service中即可。

记得要先给网络权限

复制代码
1
2
<uses-permission android:name="android.permission.INTERNET" />
  • 1

下面我们来看看Service中的代码,其中有些细节是需要注意的 

复制代码
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
package com.yzq.socketdemo.service; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.util.Log; import android.widget.TabHost; import android.widget.Toast; import com.yzq.socketdemo.common.Constants; import com.yzq.socketdemo.common.EventMsg; import org.greenrobot.eventbus.EventBus; import java.io.IOException; import java.io.OutputStream; import java.net.ConnectException; import java.net.InetSocketAddress; import java.net.NoRouteToHostException; import java.net.Socket; import java.net.SocketTimeoutException; import java.util.Timer; import java.util.TimerTask; /** * Created by yzq on 2017/9/26. * <p> * socket连接服务 */ public class SocketService extends Service { /*socket*/ private Socket socket; /*连接线程*/ private Thread connectThread; private Timer timer = new Timer(); private OutputStream outputStream; private SocketBinder sockerBinder = new SocketBinder(); private String ip; private String port; private TimerTask task; /*默认重连*/ private boolean isReConnect = true; private Handler handler = new Handler(Looper.getMainLooper()); @Override public IBinder onBind(Intent intent) { return sockerBinder; } public class SocketBinder extends Binder { /*返回SocketService 在需要的地方可以通过ServiceConnection获取到SocketService */ public SocketService getService() { return SocketService.this; } } @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { /*拿到传递过来的ip和端口号*/ ip = intent.getStringExtra(Constants.INTENT_IP); port = intent.getStringExtra(Constants.INTENT_PORT); /*初始化socket*/ initSocket(); return super.onStartCommand(intent, flags, startId); } /*初始化socket*/ private void initSocket() { if (socket == null && connectThread == null) { connectThread = new Thread(new Runnable() { @Override public void run() { socket = new Socket(); try { /*超时时间为2秒*/ socket.connect(new InetSocketAddress(ip, Integer.valueOf(port)), 2000); /*连接成功的话 发送心跳包*/ if (socket.isConnected()) { /*因为Toast是要运行在主线程的 这里是子线程 所以需要到主线程哪里去显示toast*/ toastMsg("socket已连接"); /*发送连接成功的消息*/ EventMsg msg = new EventMsg(); msg.setTag(Constants.CONNET_SUCCESS); EventBus.getDefault().post(msg); /*发送心跳数据*/ sendBeatData(); } } catch (IOException e) { e.printStackTrace(); if (e instanceof SocketTimeoutException) { toastMsg("连接超时,正在重连"); releaseSocket(); } else if (e instanceof NoRouteToHostException) { toastMsg("该地址不存在,请检查"); stopSelf(); } else if (e instanceof ConnectException) { toastMsg("连接异常或被拒绝,请检查"); stopSelf(); } } } }); /*启动连接线程*/ connectThread.start(); } } /*因为Toast是要运行在主线程的 所以需要到主线程哪里去显示toast*/ private void toastMsg(final String msg) { handler.post(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show(); } }); } /*发送数据*/ public void sendOrder(final String order) { if (socket != null && socket.isConnected()) { /*发送指令*/ new Thread(new Runnable() { @Override public void run() { try { outputStream = socket.getOutputStream(); if (outputStream != null) { outputStream.write((order).getBytes("gbk")); outputStream.flush(); } } catch (IOException e) { e.printStackTrace(); } } }).start(); } else { toastMsg("socket连接错误,请重试"); } } /*定时发送数据*/ private void sendBeatData() { if (timer == null) { timer = new Timer(); } if (task == null) { task = new TimerTask() { @Override public void run() { try { outputStream = socket.getOutputStream(); /*这里的编码方式根据你的需求去改*/ outputStream.write(("test").getBytes("gbk")); outputStream.flush(); } catch (Exception e) { /*发送失败说明socket断开了或者出现了其他错误*/ toastMsg("连接断开,正在重连"); /*重连*/ releaseSocket(); e.printStackTrace(); } } }; } timer.schedule(task, 0, 2000); } /*释放资源*/ private void releaseSocket() { if (task != null) { task.cancel(); task = null; } if (timer != null) { timer.purge(); timer.cancel(); timer = null; } if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } outputStream = null; } if (socket != null) { try { socket.close(); } catch (IOException e) { } socket = null; } if (connectThread != null) { connectThread = null; } /*重新初始化socket*/ if (isReConnect) { initSocket(); } } @Override public void onDestroy() { super.onDestroy(); Log.i("SocketService", "onDestroy"); isReConnect = false; releaseSocket(); } }
  • 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
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272

好了,连接的service我们基本就做好了,先来看看效果,调试工具使用的是一个网络调试助手,免去我们写服务端的代码。 

可以看到,断线重连,连接成功自动发送数据,连接成功发消息这些都有了,实际上数据发送失败重连也是有的,不过模拟器上间隔时间很长,不知道怎么回事,真机没有问题。

解决了service下面就是Activity于service通信的问题了。这个就简单了,我们在service中提供了一个binder,我们可以通过binder来拿到service,然后调service的sendOrder()即可 

复制代码
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
package com.yzq.socketdemo.activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.support.v7.app.AppCompatActivity; import android.widget.Button; import android.widget.EditText; import com.yzq.socketdemo.R; import com.yzq.socketdemo.service.SocketService; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; /** * Created by yzq on 2017/9/26. * <p> * mainActivity */ public class MainActivity extends AppCompatActivity { @BindView(R.id.contentEt) EditText contentEt; @BindView(R.id.sendBtn) Button sendBtn; private ServiceConnection sc; public SocketService socketService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindSocketService(); ButterKnife.bind(this); } private void bindSocketService() { /*通过binder拿到service*/ sc = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { SocketService.SocketBinder binder = (SocketService.SocketBinder) iBinder; socketService = binder.getService(); } @Override public void onServiceDisconnected(ComponentName componentName) { } }; Intent intent = new Intent(getApplicationContext(), SocketService.class); bindService(intent, sc, BIND_AUTO_CREATE); } @OnClick(R.id.sendBtn) public void onViewClicked() { String data = contentEt.getText().toString().trim(); socketService.sendOrder(data); } @Override protected void onDestroy() { super.onDestroy(); unbindService(sc); Intent intent = new Intent(getApplicationContext(), SocketService.class); stopService(intent); } }
  • 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

ok,大功告成 

版权声明:本文为博主原创文章,转载请注明地址。如果文中有什么纰漏或错误的话,请留言指正,我会及时修改。如果你觉得本文还不错的话,记得点个赞呦,希望能帮到你,谢谢。 https://blog.csdn.net/yuzhiqiang_1993/article/details/78094909
文章标签:  android socket socket socket断线重连
个人分类:  Android
  • 暴躁的码字猴 2018-02-28 15:46:37 #3楼
    请问 你家炒菜机上市没,我去买一个
  • 伤不起12 2017-12-07 10:39:57 #2楼
    能默默的问一个,怎么接收数据吗,我将inputstream用eventbus传到main界面,因为不停接收,会出现oom的
    查看回复(1)
  • wwwzwb 2017-10-15 22:45:13 #1楼
    不错,图文并茂还有源码,再看不明白就只能去工地搬砖了!
  • 上一页
  • 1
  • 下一页

android学习】断线重连机制

【解决问题】 android连接网络之后,当网络断开连接时,为了提高用户体验,android自动检测网络,当有网络时,用户无需进行多余操作,android端自动重新连接网络。 【解决方案】 1...

 SunshineTan

2016-07-27 22:41:07

阅读数:7034

关于socket判断连接断开并重连

关于socket判断连接断开并重连 以下是个线程函数 UINT CMonitorDlg::ThreadFunction(LPVOID pParam) { WSADATA wsaData; SOCKET...

 tengxiaoming

2010-08-27 01:02:00

阅读数:8423

android-socket斷開之後重新連接 - CSDN博客

最后,将SocketClient.resetSocket();放入图片中的catch{}中,捕获异常的时候重新...Websocket SSL加密之android端(带重连) 最近在开发Android手机端的websocket通信...

2018-5-25

WebSocket安卓客户端实现详解(一)--连接建立与重连 - CSDN博客

WebSocket安卓客户端实现详解(一)–连接建立与重连 今年在公司第一个需求就是...android中使用webSocket通信 概述最近公司项目准备使用WebSocket实现消息推送功能,在...

2018-3-2

您有一张免费的北京车展门票等待领取美好购车节 · 顶新

WebSocket安卓客户端实现详解(一)--连接建立与重连

今年在公司第一个需求就是基于websocket写一个客户端消息中心,现在已经上线很久了在司机这种网络环境平均一天重连8次,自认为还是不错的.当时写的时候那个心酸啊,主要因为第一次写都不知道该从哪下手,...

 zly921112

2017-06-10 00:07:03

阅读数:19672

Android:这是一份很详细的Socket使用攻略 - CSDN博客

前言Socket的使用在Android的网络编程中非常重要今天我将带大家全面了解Socket及其使用方法 目录1.网络基础1.1 计算机网络分层计算机网络分为五层:物理层、数据链路层...

2018-5-2

android端 socket长连接 架构 - CSDN博客

看过包建强的《App研发录》之后对其中的基础Activity类封装感到惊讶,一直想找一种方式去解决关于app中使用socket长连接问题,如何实现简易的封装来达到主活动中涉及...

2018-5-28

Android Socket连接(心跳检测,断线重连,状态监测等)

2017年09月27日 13.06MB 下载

android-socket斷開之後重新連接

今天研究这个问题搞了整整一天啊!终于出来了,不过我没有多大的成就感,为什么呢?因为这是我学长的劳动成果。同样的问题,我却没想出来!心塞的很啊…… 不过还是要给大家分享一下,希望给大家带来帮助! ...

 yqj234

2016-04-27 10:24:49

阅读数:405

问题:解决Android中socket自动断开连接 - 酸豆角作坊 - CSDN博客

后来查找了资料,显示原来Android中蓝牙socket通信连接时长大概为120s,如果超过这个...• Android入门实战 • socket连接,判断连接中断,如果中断,并自动重连。 ...

2017-9-19

Android:这是一份很详细的Socket使用攻略 - CSDN博客

Socket的使用在 Android网络编程中非常重要 今天我将带大家全面了解 Socket及 其...Android:RxJava 结合 Retrofit 全面实现 网络请求出错重连 Android:RxJava 结合...

2017-12-27

Socket连接Android端心跳机制实现

前面用golang写的socket服务端请移步:http://blog.csdn.net/u010072711/article/details/760821761. 把socket链接和心跳功能都放在...

 u010072711

2017-07-25 22:36:27

阅读数:7978

打印机出租,新机销售,选弘顺瑞通,绿色节能办公的首选!弘顺瑞通 · 顶新

Android中Socket使用 - CSDN博客

Android Socket用法详解 2015-11-08 16:51 73人阅读 评论(0) 收藏 举报  分类: android基础(28)   在客户/服务器通信模式中, 客户端需要...

2018-4-19

Android:最全面的Socket使用解析 - CSDN博客

版权声明:本文为博主原创文章,未经博主允许不得转载,更多文章请继续关注Carson_Ho的博客! 目录(?)[+] 前...

2018-5-23

Android-----借助MINA框架实现长连接、短连接以及断线重连

前面我们分析了MINA框架的源码,大家可以从这里进行查看,这篇博客我们使用MINA来完成项目中经常会用到的长连接、短连接断线重连功能,直接开始了;         MINA本身...

 hzw19920329

2016-08-13 17:40:31

阅读数:6750

Android中判断socket通信断开

你好!这里是风筝的博客,欢迎和我一起交流。 如果本篇博客对您有帮助,或许可以在下方评论给我留个言呀。 可以引起网络连接关闭的情况有以下4种: 1.  直接调用Socket类的close方法...

 Guet_Kite

2017-04-21 19:20:25

阅读数:4411

Android:这是一份很详细的Socket使用攻略 - CSDN博客

最后。该关闭的流和 socket。是一定要关闭的。。。 Socket的使用在 Android网络编程中非常重要 今天我将带大家全面了解 Socket 及 其使用方法  目录 1...

2018-3-7

undefined

安卓 java有效判断Socket连接断开和安卓TCP测试APP(客户+服务端一体)

1. 利用socket提供的isConnected()与isClosed()方法来判断。但这种方式只是本地判断,只是本地操作connect()或close()方法后保存的一个状态,对于远程服务器主动断...

 HelloMyPeople

2016-07-14 09:51:02

阅读数:5791

问题:解决Androidsocket自动断开连接

连接上蓝牙模块后,能够正常读数,蓝牙数据发送速率为0.03s每个。大概在发送了342个数据之后,突然接收不到数据了。...

 pursue16

2017-05-14 17:13:32

阅读数:2380

Android socket与服务器通信及心跳连接的实现

在项目中,有如下需求:Android客户端向服务器发送数据,收到服务器返回的数据发送成功标识后,客户端即与服务器建立数据一来一往的心跳连接,若服务器端断开时,客户端接收到通知,关闭Service停止发...

 androidforwell

2017-02-14 17:19:48

阅读数:6071

android socket 实现心跳包

//开一个新线程 new Thread(){ //用handle处理要发送的数据 Handler handler = new Handler(){ public voi...

 mobei1983

2016-05-27 11:01:58

阅读数:594

Androidsocket连接(心跳检测)

2016年03月23日 2.78MB 下载

Android心跳包(一)——心跳实现

连接 测试服务器:  Socket基本上都这么一个流程。 public class Test { private static final int PORT = 1234; ...

 github_27263697

2017-11-21 16:35:47

阅读数:441

Android上面如何使用带有心跳检测的Socket

由于移动设备的网络的复杂性,经常会出现网络断开,如果没有心跳包的检测,客户端只会在需要发送数据的时候才知道自己已经断线,会延误,甚至丢失服务器发送过来的数据。一下简单建立一个带有心跳检测的Socket...

 cuishiying

2015-08-12 00:45:53

阅读数:426

android连接心跳机制

在写之前,我们首先了解一下为什么android维护长连接需要心跳机制,首先我们知道,维护任何一个长连接都需要心跳机制,客户端发送一个心跳给 服务器,服务器给客户端一个心跳应答,这样就形成客户端服务器...

 rabbit_in_android

2015-11-30 22:21:32

阅读数:19654

Android-socket的基本使用,发送文字和图片以及心跳

项目需求收集通过Socket向服务器发送图片,之前没搞过,网上搜搜写了下面的例子,勉强解决了需求。为了测试切换着方便,所以方法写的有点碎了。。。 原文地址 http://blog.csdn.net/...

 qq_25806863

2017-07-20 15:55:20

阅读数:1611

Android socket通信的长连接与心跳检测

Android开发中,我们可能需要和服务器保持连接不断开,这时需要用到socket通信的长连接,并且定时发送消息检测是否是连接状态——心跳检测。 我们需要一个客户端和一个服务器端的...

 JJ583500596

2017-08-02 17:13:15

阅读数:1234

AndroidAndroid心跳包详解

在做IM通信时,都会遇到这样一个概念:心跳包。又是一个比较抽象的概念,那么心跳包到底是什么呢? 之前做的机房预定系统里,使用的Socket和服务器通信。长连接测试服务器: Socket基本上都这么...

 bless2015

2016-09-27 14:04:08

阅读数:5026

Android socket通信长连接(心跳检测)

2016年06月17日 2.78MB 下载

个人资料

关注
原创
56
粉丝
147
喜欢
195
评论
244
等级:
访问:
19万+
积分:
2483
排名:
1万+
勋章:

我的个人网站

我的个人网站

最新文章

  • Android获取SHA1值的详细步骤
  • 从天地初开到MVC再到MVP
  • rxjava2的相关封装
  • Kotlin Unresolved reference: 解决办法
  • Kotlin的变量和数据类型

博主专栏

  • 从零开始,学习web前端

    阅读量: 81096 21 篇
  • Kotlin从入门到放弃java

    阅读量: 404 2 篇

归档

  • 2018年2月1篇
  • 2018年1月3篇
  • 2017年12月3篇
  • 2017年10月5篇
  • 2017年9月5篇
  • 2017年8月1篇
  • 2017年7月5篇
  • 2017年6月3篇
  • 2017年5月6篇
  • 2017年4月4篇
  • 2017年3月7篇
  • 2017年2月3篇
  • 2017年1月7篇
  • 2016年11月1篇
  • 2016年10月2篇
  • 2016年8月1篇

展开

热门文章

  • 超简单集成Android Zxing实现扫一扫二维码

    阅读量:24982

  • Android 底部导航栏 BottomNavigationBar的简单使用

    阅读量:15197

  • Android Studio3.x新的依赖方式(implementation、api、compileOnly)

    阅读量:12346

  • Angular项目目录结构详解

    阅读量:12136

  • Angular环境搭建

    阅读量:10864

  • 2

关闭

最后

以上就是斯文往事最近收集整理的关于Android Socket连接(模拟心跳包,断线重连,发送数据等)的全部内容,更多相关Android内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部