首页
最新活动
服务器租用
香港服务器租用
台湾服务器租用
美国服务器租用
日本服务器租用
新加坡服务器租用
高防服务器
香港高防服务器
台湾高防服务器
美国高防服务器
裸金属
香港裸金属服务器
台湾裸金属服务器
美国裸金属服务器
日本裸金属服务器
新加坡裸金属服务器
云服务器
香港云服务器
台湾云服务器
美国云服务器
日本云服务器
CDN
CDN节点
CDN带宽
CDN防御
CDN定制
行业新闻
官方公告
香港服务器资讯
帮助文档
wp博客
zb博客
服务器资讯
联系我们
关于我们
机房介绍
机房托管
登入
注册
帮助文档
专业提供香港服务器、香港云服务器、香港高防服务器租用、香港云主机、台湾服务器、美国服务器、美国云服务器vps租用、韩国高防服务器租用、新加坡服务器、日本服务器租用 一站式全球网络解决方案提供商!专业运营维护IDC数据中心,提供高质量的服务器托管,服务器机房租用,服务器机柜租用,IDC机房机柜租用等服务,稳定、安全、高性能的云端计算服务,实时满足您的多样性业务需求。 香港大带宽稳定可靠,高级工程师提供基于服务器硬件、操作系统、网络、应用环境、安全的免费技术支持。
联系客服
服务器资讯
/
香港服务器租用
/
香港VPS租用
/
香港云服务器
/
美国服务器租用
/
台湾服务器租用
/
日本服务器租用
/
官方公告
/
帮助文档
Qt实践:TCP服务器和客户端的设计
发布时间:2024-02-28 09:08:47 分类:帮助文档
Qt实践:TCP服务器和客户端的设计 Qt:5.12.2 Qt Creator:4.11.1 通信方式:TCP\IP 语言:C++ 一、TCP Client的设计 客户端的界面UI包含服务器IP、服务器端口、以及一些简单的功能,数据可选ASCLL及HEX格式。当未与服务器建立连接时,该客户端的部分控件设置为禁用。 自动获取本地IP并显示在QLineEdit中(该部分参考了一篇博客,链接在文末) 'getIp()'函数可以根据不同的操作系统获取本地 IP 地址。在 Windows 系统下,通过使用 'QHostInfo::fromName(QHostInfo::localHostName())'获取本地主机信息,并存储在 'vAddressList' 列表中;在非 Windows 系统下,它直接调用 'QNetworkInterface::allAddresses()`'获取所有网络接口信息。然后,遍历地址列表 ('vAddressList'),找到一个有效的 IPv4 地址并存储在 'myipv4Address'变量中。'initialize()`'函数调用 'getIp()`'获取本地 IP 地址,并将其显示在客户端 UI 的 IP 地址输入框 ('ui->ipLineEdit') 中。 QString Client::getIp() { QString myipv4Address; #ifdef _WIN32 // Windows 系统下获取本地主机信息 QHostInfo vHostInfo = QHostInfo::fromName(QHostInfo::localHostName()); QList
vAddressList = vHostInfo.addresses(); #else // 非 Windows 系统下获取所有网络接口信息 QList
vAddressList = QNetworkInterface::allAddresses(); #endif // 遍历地址列表以查找有效的 IPv4 地址 for (int i = 0; i < vAddressList.size(); i++) { if (!vAddressList.at(i).isNull() && vAddressList.at(i) != QHostAddress::LocalHost && vAddressList.at(i).protocol() == QAbstractSocket::IPv4Protocol) { myipv4Address = vAddressList.at(i).toString(); break; } } return myipv4Address; } void Client::initialize() { QString localIP = getIp(); ui->ipLineEdit->setText(localIP); } 连接服务器 通过两个函数来更新客户端界面和连接状态。'connectToServer()'函数首先检查当前是否已连接到服务器。如果尚未连接,则从 IP 地址输入框和端口号输入框获取目标服务器的 IP 地址和端口号,并尝试连接到目标服务器。连接成功后,显示成功连接的消息框,更新连接状态和发送/接收选项,并启用发送文本框。如果连接失败,则显示连接失败的消息框。'disconnectFromServer()'函数首先检查当前是否已连接到服务器。如果已连接,则断开与服务器的连接,并更新连接状态和发送/接收选项。在断开连接后,禁用发送文本框。 void Client::connectToServer() { // 检查当前是否已连接到服务器 if (!isConnected) { // 从 IP 地址输入框和端口号输入框获取目标服务器的IP地址和端口号 QString ipAddress = ui->ipLineEdit->text(); quint16 port = ui->portLineEdit->text().toUShort(); // 尝试连接到目标服务器 tcpSocket->connectToHost(QHostAddress(ipAddress), port); // 等待连接,最多等待3秒(3000毫秒) if (tcpSocket->waitForConnected(3000)) { // 连接成功的消息框提示 QMessageBox::information(this, "Connected", "Successfully connected to server!"); // 更新连接状态和发送/接收选项 isConnected = true; updateSendOptions(true); updateRecvOptions(true); // 在成功连接后启用发送文本框 ui->sendTextEdit->setEnabled(true); } else { // 连接失败的消息框提示 QMessageBox::critical(this, "Error", "Connection failed!"); } } } void Client::disconnectFromServer() { // 检查当前是否已连接到服务器 if (isConnected) { // 断开与服务器的连接 tcpSocket->disconnectFromHost(); // 更新连接状态和发送/接收选项 isConnected = false; updateSendOptions(false); updateRecvOptions(false); // 在断开连接后禁用发送文本框 ui->sendTextEdit->setEnabled(false); } } 数据收发逻辑 'sendNewLine()'函数首先检查是否已连接到服务器。如果已连接,则根据当前选择的数据格式(ASCII 或 HEX)从发送区文本框获取数据,并将其发送到服务器。'displayReceivedData()'函数读取从服务器接收到的数据,并根据当前选择的接收数据格式(ASCII 或 HEX)将其显示在接收区文本框中。如果停止显示复选框未选中,则继续显示数据。 void Client::sendNewLine() { // 检查是否已经连接到服务器 if (isConnected) { // 检查当前选择的发送数据格式是否为 HEX 格式 if (ui->sendFormatComboBox->currentIndex() == 1) { // HEX format // 检查发送区文本框是否有数据 if (!ui->sendTextEdit->toPlainText().isEmpty()) { // 获取发送区文本内容,并清理其中的空格等空白字符 QString hexData = ui->sendTextEdit->toPlainText().simplified(); // Remove spaces // 检查处理后的十六进制字符串长度是否为偶数 if (hexData.size() % 2 != 0) { qDebug() << "Error: Incomplete hex data!"; return; } // 创建字节数组用于存储转换后的字节数据 QByteArray byteArray; byteArray.resize(hexData.length() / 2); bool ok; // 将十六进制字符串转换为字节数据 for (int i = 0; i < hexData.length(); i += 2) { QString byte = hexData.mid(i, 2); byteArray[i / 2] = static_cast
(byte.toInt(&ok, 16)); // 检查转换过程中是否有非法字符 if (!ok) { qDebug() << "Error: Invalid hex data!"; return; } } // 发送转换后的字节数据到服务器 tcpSocket->write(byteArray); } } else { // ASCII format // 检查发送区文本框是否有数据 if (!ui->sendTextEdit->toPlainText().isEmpty()) { // 将文本内容转换为 UTF-8 格式的字节数据,并发送到服务器 tcpSocket->write(ui->sendTextEdit->toPlainText().toUtf8()); } } } else { // 如果未连接到服务器,则无法发送数据 qDebug() << "Not connected to a server. Cannot send data."; } } void Client::displayReceivedData() { // 读取接收到的数据 QByteArray receivedData = tcpSocket->readAll(); QString displayData; if (ui->receiveFormatComboBox->currentIndex() == 1) { // HEX format // 如果接收格式为 HEX,则将数据以十六进制格式显示 QString hexData; for (int i = 0; i < receivedData.size(); ++i) { hexData += QString("%1 ").arg(static_cast
(receivedData.at(i)), 2, 16, QChar('0')).toUpper(); } displayData = hexData; } else { // ASCII format // 如果接收格式为 ASCII,则直接显示接收到的数据 displayData = QString::fromUtf8(receivedData); } if (!ui->stopDisplayCheckBox->isChecked()) { // 如果停止显示复选框未选中,则将数据追加到接收区域文本框中 ui->recvTextEdit->append(displayData); } } 二、TCP Server的设计 服务器部分的设计与客户端类似,以下会提供一些主要部分的代码及注释。 获取IP不再赘述,下面是服务器监听的逻辑 'on_connectButton_clicked()'函数用于启动服务器监听连接请求。首先检查服务器是否已处于监听状态。如果服务器尚未处于监听状态,则从端口号输入框获取端口号,并使用 'tcpServer->listen(QHostAddress::Any, port)`'启动服务器监听。如果启动失败,则显示错误消息。成功启动后,状态标签 ('ui->statusLabel') 显示为 "Server running: Waiting for connection..."。 'on_disconnectButton_clicked()'函数用于停止服务器监听。首先检查服务器是否正在监听。如果服务器正在监听连接,则使用 'tcpServer->close()'停止服务器监听。停止后,状态标签 ('ui->statusLabel') 显示为 "Server stopped."。 void Server::on_connectButton_clicked() { // 启动服务器监听连接请求 if (!tcpServer->isListening()) { quint16 port = ui->portLineEdit->text().toUShort(); if (!tcpServer->listen(QHostAddress::Any, port)) { QMessageBox::critical(this, "Error", "Unable to start the server!"); return; } ui->statusLabel->setText("Server running: Waiting for connection..."); } } void Server::on_disconnectButton_clicked() { // 停止服务器监听 if (tcpServer->isListening()) { tcpServer->close(); ui->statusLabel->setText("Server stopped."); } } 数据收发逻辑 'on_sendButton_clicked()'用于处理服务器端发送数据。首先检查是否与客户端连接,然后根据发送数据的格式从发送区获取数据并发送到客户端。如果未连接到客户端,则输出错误消息。 'displayReceivedData()'用于显示接收到的数据。它读取从客户端接收到的数据,并根据接收数据的格式(HEX 或 ASCII)将数据显示在接收区域。如果停止显示复选框未选中,则将数据继续到接收区。 void Server::on_sendButton_clicked() { // 检查是否与客户端连接 if (tcpSocket->state() == QAbstractSocket::ConnectedState) { // 检查发送数据的格式 if (ui->sendFormatComboBox->currentIndex() == 1) { // HEX format // 从发送区获取HEX格式的数据并发送 if (!ui->sendTextEdit->toPlainText().isEmpty()) { QString hexData = ui->sendTextEdit->toPlainText().simplified(); // 移除空格 if (hexData.size() % 2 != 0) { qDebug() << "Error: Incomplete hex data!"; return; } QByteArray byteArray; byteArray.resize(hexData.length() / 2); bool ok; for (int i = 0; i < hexData.length(); i += 2) { QString byte = hexData.mid(i, 2); byteArray[i / 2] = static_cast
(byte.toInt(&ok, 16)); if (!ok) { qDebug() << "Error: Invalid hex data!"; return; } } // 发送HEX格式的数据 tcpSocket->write(byteArray); } } else { // ASCII format // 从发送区获取ASCII格式的数据并发送 if (!ui->sendTextEdit->toPlainText().isEmpty()) { tcpSocket->write(ui->sendTextEdit->toPlainText().toUtf8()); } } } else { qDebug() << "No client connected. Cannot send data."; } } void Server::displayReceivedData() { QByteArray receivedData = tcpSocket->readAll(); QString displayData; if (ui->receiveFormatComboBox->currentIndex() == 1) { // HEX format QString hexData; for (int i = 0; i < receivedData.size(); ++i) { hexData += QString("%1 ").arg(static_cast
(receivedData.at(i)), 2, 16, QChar('0')).toUpper(); } displayData = hexData; } else { // ASCII format displayData = QString::fromUtf8(receivedData); } if (!ui->stopDisplayCheckBox->isChecked()) { appendToReceive(displayData); } } 三、功能测试 以下分为三部分进行验证,主要测试均为客户端与服务器之间的ASCLL与HEX数据收发。 1、自制客户端与野火网络调试助手之间通信 输入服务器端口8000,启动服务器监听,点击客户端连接按钮后提示“Successfully connected to server!”并且禁用的控件显示为可用状态,表明自制客户端与服务器实现了连接。当客户端以HEX格式发送数据32 32 32时,服务器接收到ASCLL数据2 2 2。 2、自制服务器与野火网络调试助手之间通信 输入服务器端口8000,启动服务器监听,点击野火客户端连接按钮后服务器的Label提示状态转为“Sever running : Waiting for connection...”表明客户端与自制服务器实现了连接。当客户端以HEX格式发送数据32 32 32时,服务器接收到ASCLL数据2 2 2。 3、自制服务器与自制客户端之间通信 输入服务器端口8000,启动服务器监听,点击客户端连接按钮后客户端提示“Successfully connected to server!”并且禁用的控件显示为可用状态,服务器的Label控件提示状态转为“Sever running : Waiting for connection...”表明自制客户端与自制服务器实现了连接。当客户端以HEX格式发送数据32 32 32时,服务器接收到ASCLL数据2 2 2。 四、程序源码 client.h #ifndef CLIENT_H #define CLIENT_H #include
#include
#include
QT_BEGIN_NAMESPACE namespace Ui { class Client; } QT_END_NAMESPACE class Client : public QMainWindow { Q_OBJECT public: Client(QWidget *parent = nullptr); ~Client(); private slots: // 槽函数声明 void connectToServer(); void disconnectFromServer(); void sendNewLine(); void clearReceivedData(); void toggleDisplay(); void displayReceivedData(); void formatChanged(int index); void updateSendOptions(bool connected); void updateRecvOptions(bool connected); void clearSend(); QString getIp(); // 获取本机IP的函数 private: Ui::Client *ui; QTcpSocket *tcpSocket; bool isConnected; void initialize(); // 初始化函数,用于显示本地IP地址; }; #endif // CLIENT_H client.cpp #include "client.h" #include "ui_client.h" #include
#include
#include
#include
Client::Client(QWidget *parent) : QMainWindow(parent), ui(new Ui::Client), tcpSocket(new QTcpSocket(this)), isConnected(false) { ui->setupUi(this); // 设置默认状态 updateSendOptions(false); // 更新发送选项状态为禁用 updateRecvOptions(false); // 更新接收选项状态为禁用 // 设置默认格式选项 ui->sendFormatComboBox->setCurrentIndex(0); // 设置发送格式为 ASCII ui->receiveFormatComboBox->setCurrentIndex(0); // 设置接收格式为 ASCII // 连接按钮信号和槽 connect(ui->connectButton, &QPushButton::clicked, this, &Client::connectToServer); connect(ui->disconnectButton, &QPushButton::clicked, this, &Client::disconnectFromServer); connect(ui->sendButton, &QPushButton::clicked, this, &Client::sendNewLine); connect(ui->clearRecvButton, &QPushButton::clicked, this, &Client::clearReceivedData); connect(ui->clearSendButton, &QPushButton::clicked, this, &Client::clearSend); connect(ui->stopDisplayCheckBox, &QCheckBox::toggled, this, &Client::toggleDisplay); connect(ui->receiveFormatComboBox, QOverload
::of(&QComboBox::currentIndexChanged), this, &Client::formatChanged); connect(tcpSocket, &QTcpSocket::readyRead, this, &Client::displayReceivedData); // 初始化窗口,显示本地 IP 地址 initialize(); } Client::~Client() { delete ui; } QString Client::getIp() { QString myipv4Address; #ifdef _WIN32 // Windows 系统下获取本地主机信息 QHostInfo vHostInfo = QHostInfo::fromName(QHostInfo::localHostName()); QList
vAddressList = vHostInfo.addresses(); #else // 非 Windows 系统下获取所有网络接口信息 QList
vAddressList = QNetworkInterface::allAddresses(); #endif // 遍历地址列表以查找有效的 IPv4 地址 for (int i = 0; i < vAddressList.size(); i++) { if (!vAddressList.at(i).isNull() && vAddressList.at(i) != QHostAddress::LocalHost && vAddressList.at(i).protocol() == QAbstractSocket::IPv4Protocol) { myipv4Address = vAddressList.at(i).toString(); break; } } return myipv4Address; } void Client::initialize() { QString localIP = getIp(); ui->ipLineEdit->setText(localIP); } void Client::connectToServer() { if (!isConnected) { QString ipAddress = ui->ipLineEdit->text(); quint16 port = ui->portLineEdit->text().toUShort(); tcpSocket->connectToHost(QHostAddress(ipAddress), port); if (tcpSocket->waitForConnected(3000)) { QMessageBox::information(this, "Connected", "Successfully connected to server!"); isConnected = true; updateSendOptions(true); updateRecvOptions(true); ui->sendTextEdit->setEnabled(true); // Enable send text box upon successful connection } else { QMessageBox::critical(this, "Error", "Connection failed!"); } } } void Client::disconnectFromServer() { if (isConnected) { tcpSocket->disconnectFromHost(); isConnected = false; updateSendOptions(false); updateRecvOptions(false); ui->sendTextEdit->setEnabled(false); // Disable send text box upon disconnection } } void Client::sendNewLine() { if (isConnected) { if (ui->sendFormatComboBox->currentIndex() == 1) { // HEX format if (!ui->sendTextEdit->toPlainText().isEmpty()) { QString hexData = ui->sendTextEdit->toPlainText().simplified(); // Remove spaces if (hexData.size() % 2 != 0) { qDebug() << "Error: Incomplete hex data!"; return; } QByteArray byteArray; byteArray.resize(hexData.length() / 2); bool ok; for (int i = 0; i < hexData.length(); i += 2) { QString byte = hexData.mid(i, 2); byteArray[i / 2] = static_cast
(byte.toInt(&ok, 16)); if (!ok) { qDebug() << "Error: Invalid hex data!"; return; } } tcpSocket->write(byteArray); } } else { // ASCII format if (!ui->sendTextEdit->toPlainText().isEmpty()) { tcpSocket->write(ui->sendTextEdit->toPlainText().toUtf8()); } } } else { qDebug() << "Not connected to a server. Cannot send data."; } } void Client::clearReceivedData() { ui->recvTextEdit->clear(); } void Client::toggleDisplay() { if (ui->stopDisplayCheckBox->isChecked()) { ui->recvTextEdit->setReadOnly(true); } else { ui->recvTextEdit->setReadOnly(false); } } void Client::displayReceivedData() { QByteArray receivedData = tcpSocket->readAll(); QString displayData; if (ui->receiveFormatComboBox->currentIndex() == 1) { // HEX format QString hexData; for (int i = 0; i < receivedData.size(); ++i) { hexData += QString("%1 ").arg(static_cast
(receivedData.at(i)), 2, 16, QChar('0')).toUpper(); } displayData = hexData; } else { // ASCII format displayData = QString::fromUtf8(receivedData); } if (!ui->stopDisplayCheckBox->isChecked()) { ui->recvTextEdit->append(displayData); } } void Client::formatChanged(int index) { Q_UNUSED(index); displayReceivedData(); } void Client::updateSendOptions(bool connected) { ui->sendButton->setEnabled(connected); ui->sendTextEdit->setEnabled(connected); ui->clearSendButton->setEnabled(connected); ui->sendFormatComboBox->setEnabled(connected); } void Client::updateRecvOptions(bool connected) { ui->clearRecvButton->setEnabled(connected); ui->stopDisplayCheckBox->setEnabled(connected); ui->receiveFormatComboBox->setEnabled(connected); } void Client::clearSend() { ui->sendTextEdit->clear(); } server.h #ifndef SERVER_H #define SERVER_H #include
#include
#include
QT_BEGIN_NAMESPACE namespace Ui { class Server; } QT_END_NAMESPACE class Server : public QMainWindow { Q_OBJECT public: explicit Server(QWidget *parent = nullptr); ~Server(); private slots: void on_connectButton_clicked(); void on_disconnectButton_clicked(); void on_sendButton_clicked(); void on_clearSendButton_clicked(); void on_clearReceiveButton_clicked(); void on_stopDisplayCheckBox_toggled(bool checked); void on_receiveFormatComboBox_currentIndexChanged(int index); private: Ui::Server *ui; QTcpServer *tcpServer; QTcpSocket *tcpSocket; QString localIP; void displayLocalIP(); void appendToReceive(const QString &message); void displayReceivedData(); }; #endif // SERVER_H server.cpp #include "server.h" #include "ui_server.h" #include
#include
#include
Server::Server(QWidget *parent) : QMainWindow(parent), ui(new Ui::Server), tcpServer(new QTcpServer(this)), tcpSocket(new QTcpSocket(this)) { ui->setupUi(this); // 显示本地IP地址 displayLocalIP(); // 监听连接请求 connect(tcpServer, &QTcpServer::newConnection, this, [this]() { // 接收连接并分配socket tcpSocket = tcpServer->nextPendingConnection(); // 当有数据到达时触发显示数据函数 connect(tcpSocket, &QTcpSocket::readyRead, this, &Server::displayReceivedData); }); } Server::~Server() { delete ui; } void Server::displayLocalIP() { // 获取本地IP地址并在UI中显示 QList
ipAddressesList = QNetworkInterface::allAddresses(); for (const QHostAddress &address : ipAddressesList) { if (address != QHostAddress::LocalHost && address.toIPv4Address()) { localIP = address.toString(); ui->localIPLineEdit->setText(localIP); break; } } } void Server::appendToReceive(const QString &message) { // 将接收到的信息追加到接收区 if (!ui->stopDisplayCheckBox->isChecked()) { ui->receiveTextEdit->append(message); } } void Server::on_connectButton_clicked() { // 启动服务器监听连接请求 if (!tcpServer->isListening()) { quint16 port = ui->portLineEdit->text().toUShort(); if (!tcpServer->listen(QHostAddress::Any, port)) { QMessageBox::critical(this, "Error", "Unable to start the server!"); return; } ui->statusLabel->setText("Server running: Waiting for connection..."); } } void Server::on_disconnectButton_clicked() { // 停止服务器监听 if (tcpServer->isListening()) { tcpServer->close(); ui->statusLabel->setText("Server stopped."); } } void Server::on_sendButton_clicked() { // 检查是否与客户端连接 if (tcpSocket->state() == QAbstractSocket::ConnectedState) { // 检查发送数据的格式 if (ui->sendFormatComboBox->currentIndex() == 1) { // HEX format // 从发送区获取HEX格式的数据并发送 if (!ui->sendTextEdit->toPlainText().isEmpty()) { QString hexData = ui->sendTextEdit->toPlainText().simplified(); // 移除空格 if (hexData.size() % 2 != 0) { qDebug() << "Error: Incomplete hex data!"; return; } QByteArray byteArray; byteArray.resize(hexData.length() / 2); bool ok; for (int i = 0; i < hexData.length(); i += 2) { QString byte = hexData.mid(i, 2); byteArray[i / 2] = static_cast
(byte.toInt(&ok, 16)); if (!ok) { qDebug() << "Error: Invalid hex data!"; return; } } // 发送HEX格式的数据 tcpSocket->write(byteArray); } } else { // ASCII format // 从发送区获取ASCII格式的数据并发送 if (!ui->sendTextEdit->toPlainText().isEmpty()) { tcpSocket->write(ui->sendTextEdit->toPlainText().toUtf8()); } } } else { qDebug() << "No client connected. Cannot send data."; } } void Server::on_clearSendButton_clicked() { // 清空发送区 ui->sendTextEdit->clear(); } void Server::on_clearReceiveButton_clicked() { // 清空接收区 ui->receiveTextEdit->clear(); } void Server::on_stopDisplayCheckBox_toggled(bool checked) { // 控制是否显示接收到的数据 Q_UNUSED(checked); displayReceivedData(); } void Server::displayReceivedData() { QByteArray receivedData = tcpSocket->readAll(); QString displayData; if (ui->receiveFormatComboBox->currentIndex() == 1) { // HEX format QString hexData; for (int i = 0; i < receivedData.size(); ++i) { hexData += QString("%1 ").arg(static_cast
(receivedData.at(i)), 2, 16, QChar('0')).toUpper(); } displayData = hexData; } else { // ASCII format displayData = QString::fromUtf8(receivedData); } if (!ui->stopDisplayCheckBox->isChecked()) { appendToReceive(displayData); } } void Server::on_receiveFormatComboBox_currentIndexChanged(int index) { Q_UNUSED(index); // 处理接收数据的格式变化 displayReceivedData(); } 五、工程文件 本人也是刚开始学习,里面可能存在一些不对的地方,欢迎留言讨论。 链接1为工程文件,链接2为获取本地IP的博客,链接3为封包的博客。 https://download..net/download/please_take/88691846https://blog..net/weixin_34245082/article/details/92270355?spm=1001.2014.3001.5506https://blog..net/F_Xiao_bai/article/details/130419561?spm=1001.2014.3001.5506
上一篇
台湾服务器排名
下一篇
vps 被黑
相关文章
【问题解决】VSCode1.86.0版+拓展Remote-SSHv0.108 无法连接到VSCode服务器(VSCode无法远程连接到Linux)
群晖NAS配置之自有服务器frp实现内网穿透
有服务器怎么做游戏吗
保姆级教程——将springboot项目部署到阿里云服务器(小白包会)
服务器和域名怎么关联起来
百度cdn加速怎么样
在外SSH远程连接macOS服务器【cpolar内网穿透】
软件AutoID Network Navigator设置基恩士扫码枪的使用教程
【免费教程】2024年Palworld幻兽帕鲁自建服务器方法
香港云服务器租用推荐
服务器租用资讯
·广东云服务有限公司怎么样
·广东云服务器怎么样
·广东锐讯网络有限公司怎么样
·广东佛山的蜗牛怎么那么大
·广东单位电话主机号怎么填写
·管家婆 花生壳怎么用
·官网域名过期要怎么办
·官网邮箱一般怎么命名
·官网网站被篡改怎么办
服务器租用推荐
·美国服务器租用
·台湾服务器租用
·香港云服务器租用
·香港裸金属服务器
·香港高防服务器租用
·香港服务器租用特价
7*24H在线售后
高可用资源,安全稳定
1v1专属客服对接
无忧退款试用保障
德讯电讯股份有限公司
电话:00886-982-263-666
台湾总部:台北市中山区建国北路一段29号3楼
香港分公司:九龙弥敦道625号雅兰商业二期906室
服务器租用
香港服务器
日本服务器
台湾服务器
美国服务器
高防服务器购买
香港高防服务器出租
台湾高防服务器租赁
美国高防服务器DDos
云服务器
香港云服务器
台湾云服务器
美国云服务器
日本云服务器
行业新闻
香港服务器租用
服务器资讯
香港云服务器
台湾服务器租用
zblog博客
香港VPS
关于我们
机房介绍
联系我们
Copyright © 1997-2024 www.hkstack.com All rights reserved.