我正在为基于套接字接口的Raspberry PI开发应用程序。主要的想法是Raspberry将连接到传感器,收集数据并通过WiFi将其发送到Android设备。从Android我可以与传感器发送一些命令进行通信。我是这种开发的初学者,并且关于QTcpSocket的一些教程我已经创建了一个简单的客户端 - 服务器应用程序,但它只是在一个方向。服务器侦听客户端发送的内容。你能帮助我把它改进为双向沟通吗?我已经读过QTcpSocket不需要线程来解决这类问题,但我找不到任何解决方案。
我将不胜感激任何帮助!
server.cpp:
#include "server.h"
#include <QTcpServer>
#include <QTcpSocket>
#include <cstdio>
#include <QtDebug>
Server::Server(QObject *parent) :
QObject(parent)
{
server = new QTcpServer(this);
connect(server, SIGNAL(newConnection()),
this, SLOT(on_newConnection()));
}
void Server::listen()
{
server->listen(QHostAddress::Any, 5100);
}
void Server::on_newConnection()
{
socket = server->nextPendingConnection();
if(socket->state() == QTcpSocket::ConnectedState)
{
printf("New connection established.\n");
qDebug()<<socket->peerAddress();
}
connect(socket, SIGNAL(disconnected()),
this, SLOT(on_disconnected()));
connect(socket, SIGNAL(readyRead()),
this, SLOT(on_readyRead()));
}
void Server::on_readyRead()
{
while(socket->canReadLine())
{
QByteArray ba = socket->readLine();
if(strcmp(ba.constData(), "!exit\n") == 0)
{
socket->disconnectFromHost();
break;
}
printf(">> %s", ba.constData());
}
}
void Server::on_disconnected()
{
printf("Connection disconnected.\n");
disconnect(socket, SIGNAL(disconnected()));
disconnect(socket, SIGNAL(readyRead()));
socket->deleteLater();
}
client.cpp
#include "client.h"
#include <QTcpSocket>
#include <QHostAddress>
#include <cstdio>
Client::Client(QObject *parent) : QObject(parent)
{
socket = new QTcpSocket(this);
printf("try to connect.\n");
connect(socket, SIGNAL(connected()),
this, SLOT(on_connected()));
}
void Client::on_connected()
{
printf("Connection established.\n");
char buffer[1024];
forever
{
while(socket->canReadLine())
{
QByteArray ba = socket->readLine();
printf("from server: %s", ba.constData());
}
printf(">> ");
gets(buffer);
int len = strlen(buffer);
buffer[len] = '\n';
buffer[len+1] = '\0';
socket->write(buffer);
socket->flush();
}
}
void Client::connectToServer()
{
socket->connectToHost(QHostAddress::LocalHost, 5100);
}
答案 0 :(得分:5)
从架构的角度来看,您应首先在服务器和客户端之间定义一些通信规则(消息流)。
然后根据定义的流程从(到)QTCPSocket实例读取(写入)。
例如,您可以在服务器端读取数据,检查应该回答的内容,并将响应写入您已阅读的同一个套接字。对于面向行的消息(仅适用于它们),代码可能如下所示: void Server::on_readyRead()
{
// "while" loop would block until at least one whole line arrived
// I would use "if" instead
if(socket->canReadLine())
{
QByteArray ba = socket->readLine();
QByteArray response;
// some code which parses arrived message
// and prepares response
socket->write(response);
}
//else just wait for more data
}
就个人而言,我会移动解析并从on_readyRead()插槽发送响应以避免阻塞事件循环太长时间,但由于您是网络编程的初学者,我只是想澄清可以采取哪些方法来实现双向通信。
有关详细信息,请参阅http://qt-project.org/doc/qt-4.8/qtnetwork.html
请记住检查整个邮件是否已在客户端和服务器端都到达。如果您使用自己的协议(不是HTTP,FTP或其他标准化的协议),您可以在消息开头添加消息长度。
答案 1 :(得分:1)
您需要做的就是从客户端或服务器写入/读取套接字。 TCP连接已经是双向连接。
forever
中的Client
循环可能存在一些问题。您应该以与服务器相同的方式使用套接字上的readyRead
信号并放弃forever
循环。
以非阻塞方式处理键盘输入,而不是使用gets()
。 gets()
将阻止主线程并阻止它运行事件循环。这不是处理您案例中的最佳方法,因为您希望能够同时处理来自服务器和用户的数据。
也许从控制台应用程序看一下键盘处理:
using-qtextstream-to-read-stdin-in-a-non-blocking-fashion
或者将其设为GUI应用程序并使用QPlainTextEdit
。