背景:安卓设备通过usb网络共享给Linux,此时安卓设备与linux处于同一网络环境,符合使用socket的条件,linux做客户端,安卓做服务端
1.QT使用Socket
(1).在工程文件中加入
QT += network
(2).导包以及写一些槽函数用做数据传输与状态接收
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtNetwork/QTcpSocket>
#include <QMainWindow>
#include <QTcpServer>
#include "QTimer"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
//用做读取服务端发送的数据
void readData();
//获取当前socket的连接状态
void displayError(QAbstractSocket::SocketError);
private:
Ui::MainWindow *ui;
QTcpSocket *socket;
};
#endif // MAINWINDOW_H
(3).实现Socket的数据互发与接收
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QFile"
#include "QTextCodec"
#include "QDebug"
#include "QFontDatabase"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
socket = new QTcpSocket(this);
socket->abort();
//这个地方是重点,因为安卓端我没有设置ip,那么这里的ip就是USB共享所分配的ip,可以进入安卓端使用ifconfig获取到ip地址
//端口9999是我在安卓服务端设置的,等会安卓端代码会有写
socket->connectToHost("192.168.XXX",9999);
connect(socket, &QTcpSocket::readyRead, this, &MainWindow::readData);
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(displayError(QAbstractSocket::SocketError)));
}
void MainWindow::readData() {
qDebug() << "******************************clein====********************************";
QString data = socket->readAll();
QTextCodec* codec = QTextCodec::codecForName("UTF-8");
QString strData = codec->toUnicode(data.toUtf8());
qDebug() << "readData message==="<<strData; // 输出 "11111"
qDebug() << "******************************clein********************************\n";
/*******************************读取到数据以后自动发送数据给服务端**********************************/
// 用于暂存要发送的数据
QString datas = "on_pushButton_2_clicked"; // 要发送的数据
// 将数据转换为 UTF-8 编码
QTextCodec* codecs = QTextCodec::codecForName("UTF-8");
QByteArray utf8Data = codecs->fromUnicode(datas);
// 发送数据
socket->write(utf8Data);
socket->flush();
}
void MainWindow::displayError(QAbstractSocket::SocketError)
{
qDebug() << "displayError error===="<<socket->errorString();
}
MainWindow::~MainWindow()
{
delete ui;
}
到这里QT代码就写完了,接下来我们看一下安卓端的发送与接收:
2.安卓使用Socket,直接上服务端代码(Kotlin)
package com.jk.rtk
import android.content.Context
import android.net.ConnectivityManager
import android.net.wifi.WifiManager
import android.os.Build
import android.util.Log
import java.io.IOException
import java.io.InputStream
import java.io.OutputStreamWriter
import java.net.*
import java.util.*
object SocketServer {
private val TAG = SocketServer::class.java.simpleName
var SOCKET_PORT = 9999
private var socket: Socket? = null
private var serverSocket: ServerSocket? = null
private lateinit var mCallback: ServerCallback
var result = true
/**
* 开启服务
*/
fun startServer(callback: ServerCallback): Boolean {
Log.i(TAG, "startServer: ")
mCallback = callback
Thread {
try {
serverSocket = ServerSocket(SOCKET_PORT)
while (result) {
socket = serverSocket?.accept()
mCallback.otherMsg("${socket?.inetAddress} to connected")
ServerThread(socket!!, mCallback).start()
}
} catch (e: IOException) {
e.printStackTrace()
result = false
}
}.start()
return result
}
/**
* 关闭服务
*/
fun stopServer() {
Log.i(TAG, "stopServer: ")
socket?.apply {
//shutdownInput()
//shutdownOutput()
close()
}
serverSocket?.close()
}
/**
* 发送到客户端
*/
fun sendToClient(msg: String) {
Thread {
if (socket!!.isClosed) {
Log.e(TAG, "sendToClient: Socket is closed")
return@Thread
}
Log.e(TAG, "sendToClient: msg====$msg")
try {
val out = OutputStreamWriter(socket!!.getOutputStream(), "UTF-8")
out.write(msg)
out.flush()
mCallback.otherMsg("toClient: $msg")
Log.d(TAG, "发送到客户端成功")
} catch (e: IOException) {
e.printStackTrace()
Log.e(TAG, "向客户端发送消息失败")
}
}.start()
}
/*
* 获取USB共享的ip地址
* */
fun getUsbTetheringIpAddress(): String? {
try {
val interfaces: Enumeration<NetworkInterface> = NetworkInterface.getNetworkInterfaces()
while (interfaces.hasMoreElements()) {
val intf: NetworkInterface = interfaces.nextElement()
val addresses = intf.interfaceAddresses
for (addr in addresses) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (addr.networkPrefixLength >= 16 && !addr.address.isLinkLocalAddress) {
return addr.address.hostAddress
}
} else {
if (addr.address.isSiteLocalAddress && !addr.address.isLinkLocalAddress) {
return addr.address.hostAddress
}
}
}
}
} catch (e: Exception) {
e.printStackTrace()
}
return null
}
class ServerThread(private val socket: Socket, private val callback: ServerCallback) :
Thread() {
override fun run() {
val inputStream: InputStream?
try {
inputStream = socket.getInputStream()
val buffer = ByteArray(1024)
var len: Int
var receiveStr = ""
if (inputStream.available() == 0) {
Log.e(TAG, "inputStream.available() == 0")
}
while (inputStream.read(buffer).also { len = it } != -1) {
receiveStr += String(buffer, 0, len, Charsets.UTF_8).trim()
if (len < 1024) {
Log.e(TAG, "inputStream.receiveStr == $receiveStr")
callback.receiveClientMsg(true, receiveStr)
receiveStr = ""
}
}
} catch (e: IOException) {
e.printStackTrace()
e.message?.let { Log.e("socket error", it) }
callback.receiveClientMsg(false, "")
}
}
}
}
调用方式:这里用的java方式
(1).先启动服务 与回调函数
boolean isSocket = SocketServer.INSTANCE.startServer(new ServerCallback() {
@Override
public void receiveClientMsg(boolean success, @NonNull String msg) {
Log.e("TAG", "SocketServer receiveClientMsg success=" + success + " msg=" + msg);
}
@Override
public void otherMsg(@NonNull String msg) {
Log.e("TAG", "SocketServer otherMsg msg=" + msg);
}
});
(2).发送数据: SocketServer.INSTANCE.sendToClient("json");
linux运行截图
安卓端运行截图