我正在尝试在两台计算机之间设置TCP通信框架。我希望每台计算机都能将数据发送给另一台计算机。因此,计算机A将执行计算,并将其发送到计算机B.计算机B然后将读取该数据,使用它执行计算,并将结果发送回计算机A.计算机A将等到它从计算机B接收到某些东西之前继续执行另一次计算,并将其发送到计算机B.
这似乎在概念上很简单,但我无法找到一个通过TCP详细说明双向(双向)通信的示例。我只找到了单向服务器 - 客户端通信,服务器将数据发送到客户端。这些是我到目前为止密切关注的一些例子:
我基本上希望有两个“服务器”相互通信。我相信上面的同步方法对于我正在尝试做的事情很重要。但我正在努力通过单个插槽设置双向通信框架。
如果有人可以指出我描述如何设置与TCP的双向通信的示例,或者从我上面链接的示例中给出一些关于如何设置它的指示,我将非常感激。我对TCP和网络通信框架都很陌生,可能有很多我可能会误解,所以如果我能得到一些关于如何继续的明确指示会很棒。
答案 0 :(得分:2)
TCP本质上是双向的。获得一种方式(客户端连接到服务器)。之后,两端都可以完全相同的方式使用send和recv。
答案 1 :(得分:2)
#include <QAbstractSocket>
#include <QtNetwork>
#include <QTcpServer>
#include <QTcpSocket>
QTcpSocket* m_pTcpSocket;
连接到主机:使用tcp套接字设置连接并实现您的插槽。如果数据字节可用,则readyread()信号将被激活。
void connectToHost(QString hostname, int port){
if(!m_pTcpSocket)
{
m_pTcpSocket = new QTcpSocket(this);
m_pTcpSocket->setSocketOption(QAbstractSocket::KeepAliveOption,1);
}
connect(m_pTcpSocket,SIGNAL(readyRead()),SLOT(readSocketData()),Qt::UniqueConnection);
connect(m_pTcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),SIGNAL(connectionError(QAbstractSocket::SocketError)),Qt::UniqueConnection);
connect(m_pTcpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),SIGNAL(tcpSocketState(QAbstractSocket::SocketState)),Qt::UniqueConnection);
connect(m_pTcpSocket,SIGNAL(disconnected()),SLOT(onConnectionTerminated()),Qt::UniqueConnection);
connect(m_pTcpSocket,SIGNAL(connected()),SLOT(onConnectionEstablished()),Qt::UniqueConnection);
if(!(QAbstractSocket::ConnectedState == m_pTcpSocket->state())){
m_pTcpSocket->connectToHost(hostname,port, QIODevice::ReadWrite);
}
}
写:
void sendMessage(QString msgToSend){
QByteArray l_vDataToBeSent;
QDataStream l_vStream(&l_vDataToBeSent, QIODevice::WriteOnly);
l_vStream.setByteOrder(QDataStream::LittleEndian);
l_vStream << msgToSend.length();
l_vDataToBeSent.append(msgToSend);
m_pTcpSocket->write(l_vDataToBeSent, l_vDataToBeSent.length());
}
读:
void readSocketData(){
while(m_pTcpSocket->bytesAvailable()){
QByteArray receivedData = m_pTcpSocket->readAll();
}
}
答案 2 :(得分:2)
这个答案不会进入细节,但它应该给你一个大致的想法,因为那是你真正想要的。我之前从未使用过Qt,我直接使用BSD风格的套接字或使用自己的包装器来完成所有网络代码。
考虑的事情:
'\0'
,'\n'
和"\r\n"
。如果您的协议的其余部分也是基于文本的,这意味着它更容易调试。p
版本包括原子信号掩码更改。我不建议使用它们;相反,如果您需要信号,请将signalfd
添加到集合中,或者使用信号处理程序和(非阻塞,小心!)管道来模拟它。select
/ pselect
是经典之作,随处可见。不能有超过FD_SETSIZE
个文件描述符,这些描述符可能非常小(但如果你足够小心,可以在命令行上#define
d。使用稀疏集合效率低。超时为微秒select
为pselect
和poll
的纳秒时间,但您可能无法实现这一点。只有在没有其他选择的情况下才能使用此功能。ppoll
/ FD_SETSIZE
解决了稀疏集的问题,更重要的是解决了超过poll
个文件描述符的问题。它确实使用了更多内存,但使用起来更简单。 ppoll
是POSIX,epoll
是特定于GNU的。对于两者而言,API为超时提供纳秒粒度,但您可能无法获得该超时。如果您需要BSD兼容性并且不需要大规模的可扩展性,或者如果您只有一个套接字并且不想处理epoll
的麻烦,我建议您这样做。epoll
解决了每次都必须重新指定文件描述符和事件列表的问题。通过保留文件描述符列表。除此之外,这意味着当发生低级内核事件时,无论用户程序是否已经在系统调用中,都可以使poll
立即知道。支持边缘触发模式,但除非您确定了解它,否则不要使用它。它的API只为超时提供毫秒级的粒度,但无论如何,这可能都是你可以依赖的。如果你只能定位Linux,我强烈建议你使用它,除非你可以一次只保证一个套接字,在这种情况下kqueue
更简单。epoll
位于BSD派生系统上,包括Mac OS X.它应该解决与O_NONBLOCK
相同的问题,但不是通过使用文件描述符来保持简单,而是全部各种奇怪的结构,并没有遵循&#34;只做一件事&#34;原理。我从来没用过它。如果您需要在BSD上实现大规模可扩展性,请使用此选项。connect
并禁用Nagle的算法(因为您自己正在进行缓冲),除了accept
之前可能{建立了连接,因为这需要混淆逻辑,特别是如果你想要使用多个DNS结果。listen
套接字处理程序中的read/write
和accept
/ {{1}中的connect
系列ed处理程序。对于其他类型的套接字,您需要send/recv
系列。请参阅&#34;另见&#34;在他们的手册页中获取更多信息 - 有时候其中一个对你有用,在之前执行此操作你在API设计中硬编码太多了。TCP_CORK
可能意味着不同的设计,但我还没有使用它。编辑2019:
无论您是否使用,D-Bus和0MQ的文档都值得一读。特别值得考虑的是3种对话:
D-Bus特别做出了很多看起来很奇怪的决定,但确实有理由(根据用例可能相关或不相关)。通常,它仅在本地使用。
0MQ是较低级别的,其大多数是&#34;缺点&#34;通过建立它来解决。小心MxN问题;您可能希望人为地创建一个代理节点,仅用于容易发生的消息。
答案 3 :(得分:0)
看看QWebSocket,这是基于HTTP的,它也允许HTTPS