赞
踩
Android——Tcp服务端
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
Tcp分为服务端(网络应用程序)和客户端(网络应用程序),Tcp通信过程,首先打开服务器监听自己的网络通信端口(假设为7628),打开客户端,设置好要连接的ip地址和服务器的网络通信端口(7628),这样服务器监听到网络通信端口有连接,二者就建立了连接。
客户端:可以连接服务端、发送数据、接收数据、关闭连接等。
服务端:可以实现绑定通信端口,接收客户端连接、接收数据、发送数据等。
在java项目中我们可以较为快捷地使用TCP通讯,但想要在Android中使用还有很多要注意的地方。下面我们来学习下Tcp服务端在Android上的实现。
我之前做过一个项目里有个要通过Tcp获取智能手环上电量、心率,血压血氧、步数等基本数据的功能。(这里只是个功能一样的简单小Demo,报文需要处理才能看到想要的信息)
服务端ServerSocket的构造方法:
1、ServerSocket():构造一个新的未绑定的ServerSocket。
2、ServerSocket(int port):构造一个新的ServerSocket并绑定到指定端口,如果port等于0,则端口由系统自动分配。
3、ServerSocket(int port,int backlog):构造一个新的ServerSocket并绑定到指定端口以及指定进入队列的数目。如果port等于0,则端口由系统自动分配。
4、ServerSocket(int port,int backlog,InetAddress localAddress):构造一个新的ServerSocket并绑定到指定端口以及指定进入队列的数目。如果port等于0,则端口由系统自动分配。如果localAddress为null,则可以使用任意地址。
Tcp服务端使用步骤为:
①创建ServerSocket,绑定指定端口
- try {
- //开启服务、指定端口号
- socket = new ServerSocket(mServerPort);
- } catch (IOException e) {
- e.printStackTrace();
- Toast.makeText(this, "服务开启失败", Toast.LENGTH_SHORT).show();
- return;
- }
②调用ServerSocket的accept(),监听连接请求
③调用Socket类中的getInputStream()和getOutputStream()获取输入输出流
- class SocketAcceptThread extends Thread {
- @Override
- public void run() {
- try {
- //等待客户端的连接,Accept会阻塞,直到建立连接,
- //所以需要放在子线程中运行。
- mSocket = socket.accept();
- //获取输入流
- mInStream = mSocket.getInputStream();
- //获取输出流
- mOutStream = mSocket.getOutputStream();
- } catch (IOException e) {
- e.printStackTrace();
- startAccept();
- return;
- }
- Log.i(TAG, "accept success");
- SocketReceive();
- }
- }

④接收、发送数据
- /**
- * 发送
- */
- private void sendText() {
- if (mSocket == null) {
- Toast.makeText(MainActivity.this, "没有客户端连接", Toast.LENGTH_LONG).show();
- return;
- }
- String str = content.getText().toString();
- if (str.length() == 0) {
- return;
- }
- Message msg = new Message();
- msg.what = Two;
- msg.obj = str;
- mSubThreadHandler.sendMessage(msg);
- }
-
- private void writeMsg(String msg) {
- if (msg.length() == 0 || mOutStream == null) {
- return;
- }
- try {
- //发送
- mOutStream.write(msg.getBytes());
- mOutStream.flush();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }

int count = mInStream.read(buffer);
⑤关闭服务
- if (socket != null) {
- try {
- socket.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
注意: 在清单文件中添加权限
<uses-permission android:name="android.permission.INTERNET"/>
下面是MainActivity.java完整代码 :
- public class MainActivity extends AppCompatActivity implements View.OnClickListener {
- /**
- * 设置
- */
- private Button setting;
- /**
- * 开启服务
- */
- private Button open_service;
- /**
- * 输入内容
- */
- private EditText content;
- /**
- * 发送
- */
- private Button send_out;
- /**
- * 接收到的数据
- */
- private EditText receive;
- private final String TAG = "MainActivity";
- private static final char HexCharArr[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
- /**
- * 服务端端口
- */
- private int mServerPort;
- private SharedPreferences sp;
- private static final String PORT = "port";
- public Socket mSocket;
- private HandlerThread mHandlerThread;
- /**
- * 子线程中的Handler实例
- */
- private Handler mSubThreadHandler;
- private SocketAcceptThread mAcceptThread;
- private SocketReceiveThread mReceiveThread;
- private ServerSocket socket;
- /**
- * 输出流
- */
- private OutputStream mOutStream;
- /**
- * 输入流
- */
- private InputStream mInStream;
- private static final int One = 1;
- private static final int Two = 2;
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(@NonNull Message msg) {
- switch (msg.what) {
- case One:
- String sb = receive.getText().toString() + "\r\n" + (String) msg.obj;
- receive.setText(sb);
- break;
- default:
- break;
- }
- }
- };
-
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- setting = findViewById(R.id.setting);
- open_service = findViewById(R.id.open_service);
- content = findViewById(R.id.content);
- send_out = findViewById(R.id.send_out);
- receive = findViewById(R.id.receive);
- setting.setOnClickListener(this);
- open_service.setOnClickListener(this);
- send_out.setOnClickListener(this);
- //获取sharedPreferences对象
- sp = getSharedPreferences("settings", Context.MODE_PRIVATE);
- //如果key不存在,则返回默认defValue
- mServerPort = sp.getInt(PORT, 7628);
- initHandlerThraed();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- Log.i(TAG, "onDestory");
- closeConnect();
- if (socket != null) {
- try {
- socket.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- private void closeConnect() {
- try {
- if (mOutStream != null) {
- mOutStream.close();
- }
- if (mInStream != null) {
- mInStream.close();
- }
- if (mSocket != null) {
- mSocket.close(); //关闭socket
- mSocket = null;
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- if (mReceiveThread != null) {
- mReceiveThread.threadExit();
- mReceiveThread = null;
- }
- }
-
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- //设置
- case R.id.setting:
- set();
- break;
- //开启服务
- case R.id.open_service:
- startServer();
- break;
- //发送
- case R.id.send_out:
- sendText();
- break;
- default:
- break;
- }
- }
-
- /**
- * 设置
- */
- private void set() {
- //获取布局
- View setview = LayoutInflater.from(this).inflate(R.layout.port, null);
- //获取布局中的控件
- final EditText editport = (EditText) setview.findViewById(R.id.server_port);
- Button ensureBtn = (Button) setview.findViewById(R.id.server_ok);
- editport.setText(sp.getInt(PORT, 7628) + "");
-
- final android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(this);
- //设置dialog显示一个view
- builder.setView(setview);
- //dialog显示
- final AlertDialog dialog = builder.show();
- ensureBtn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- String port = editport.getText().toString();
- if (port != null && port.length() > 0) {
- mServerPort = Integer.parseInt(port);//将内容转换成整数
- }
- SharedPreferences.Editor editor = sp.edit(); //SharedPreferences.Editor 简单的数据存储
- editor.putInt(PORT, mServerPort); //存储数据
- editor.commit(); //提交
- dialog.dismiss(); //dialog消失
- }
- });
- }
-
- /**
- * 开启服务
- */
- void startServer() {
- try {
- //开启服务、指定端口号
- socket = new ServerSocket(mServerPort);
- } catch (IOException e) {
- e.printStackTrace();
- Toast.makeText(this, "服务开启失败", Toast.LENGTH_SHORT).show();
- return;
- }
- startAccept();
- Toast.makeText(this, "服务开启", Toast.LENGTH_LONG).show();
- }
-
- /**
- * 开启SocketAcceptThread()线程
- */
- private void startAccept() {
- mAcceptThread = new SocketAcceptThread();
- mAcceptThread.start();
- }
-
- class SocketAcceptThread extends Thread {
- @Override
- public void run() {
- try {
- //等待客户端的连接,Accept会阻塞,直到建立连接,
- //所以需要放在子线程中运行。
- mSocket = socket.accept();
- //获取输入流
- mInStream = mSocket.getInputStream();
- //获取输出流
- mOutStream = mSocket.getOutputStream();
- } catch (IOException e) {
- e.printStackTrace();
- startAccept();
- return;
- }
- Log.i(TAG, "accept success");
- SocketReceive();
- }
- }
-
- private void SocketReceive() {
- mReceiveThread = new SocketReceiveThread();
- mReceiveThread.start();
- }
-
- class SocketReceiveThread extends Thread {
- private boolean threadExit = false;
-
- @Override
- public void run() {
- byte[] buffer = new byte[1024];
- while (threadExit == false) {
- try { //读取数据,返回值表示读到的数据长度。-1表示结束
- int count = mInStream.read(buffer);
- if (count == -1) {
- Log.i(TAG, "read read -1");
- startAccept();
- break;
- } else {
- String receiveData;
- receiveData = byteArrToHex(buffer);
- Log.i(TAG, "read buffer:" + receiveData + ",count=" + count);
- Message msg = new Message();
- msg.what = One;
- msg.obj = receiveData;
-
- mHandler.sendMessage(msg);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- void threadExit() {
- threadExit = true;
- }
- }
-
- /**
- * 发送
- */
- private void sendText() {
- if (mSocket == null) {
- Toast.makeText(MainActivity.this, "没有客户端连接", Toast.LENGTH_LONG).show();
- return;
- }
- String str = content.getText().toString();
- if (str.length() == 0) {
- return;
- }
- Message msg = new Message();
- msg.what = Two;
- msg.obj = str;
- mSubThreadHandler.sendMessage(msg);
- }
-
- private void writeMsg(String msg) {
- if (msg.length() == 0 || mOutStream == null) {
- return;
- }
- try {
- //发送
- mOutStream.write(msg.getBytes());
- mOutStream.flush();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * 字节数组转换十六进制
- */
- public static String byteArrToHex(byte[] btArr) {
- char strArr[] = new char[btArr.length * 2];
- int i = 0;
- for (byte bt : btArr) {
- strArr[i++] = HexCharArr[bt >>> 4 & 0xf];
- strArr[i++] = HexCharArr[bt & 0xf];
- }
- return new String(strArr);
- }
-
- private void initHandlerThraed() {
- //创建HandlerThread实例
- mHandlerThread = new HandlerThread("handler_thread");
- //开始运行线程
- mHandlerThread.start();
- //获取HandlerThread线程中的Looper实例
- Looper loop = mHandlerThread.getLooper();
- //创建Handler与该线程绑定。
- mSubThreadHandler = new Handler(loop) {
- @Override
- public void handleMessage(Message msg) {
- Log.i(TAG, "mSubThreadHandler handleMessage thread:" + Thread.currentThread());
- switch (msg.what) {
- case Two:
- writeMsg((String) msg.obj);
- break;
- default:
- break;
- }
- }
- };
- }
-
- }

最后是运行效果:设置端口、开启服务、获取的数据(需要处理)
Demo中用到的Handler、dialog对话框、SharedPreferences不理解的可以参考一下我之前的发布的文章。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。