四、Socket通信
c++的socket通信非常麻烦,并且在不同的平台上实现是不同的
Qt的socket可以实现跨平台
Qt中Socket通信的类:
用于TCP/IP通信,作为服务器端套接字使用
用于TCP/IP通信,作为客户端套接字使用
用于UDP通信,服务端和客户端均使用此套接字
1. tcp通信
1.服务端需要监听一个端口
2.客户端需要连接上服务端才能通信
1、客户端ClientWindow.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 | ClientWindow::ClientWindow(QWidget* parent):QWidget(parent) {
//创建QTCPSocket指针对象
socket = new QTcpSocket(this);
//设置大小
setFixedSize(600,600);
//设置标题
setWindowTitle("客户端");
//创建布局
QVBoxLayout *layout = new QVBoxLayout;
QHBoxLayout *hl = new QHBoxLayout;
QFormLayout*fl = new QFormLayout;
QLineEdit*ipEdit = new QLineEdit;
QLineEdit*portEdit = new QLineEdit;
ipEdit->setText("127.0.0.1");
portEdit->setText("6666");
QPushButton*connectBtn = new QPushButton("连接");
fl->addRow("服务器 ip:",ipEdit);
fl->addRow("服务器端口:",portEdit);
hl->addLayout(fl);
hl->addWidget(connectBtn);
QTextEdit *recvMsg = new QTextEdit;
QTextEdit *sendMsg = new QTextEdit;
recvMsg->setEnabled(false);
QHBoxLayout *btnLayout = new QHBoxLayout;
QPushButton*sendBtn = new QPushButton("发送");
QPushButton*closeBtn = new QPushButton("关闭");
layout->addLayout(hl);
layout->addWidget(recvMsg);
layout->addWidget(sendMsg);
btnLayout->addWidget(sendBtn);
btnLayout->addWidget(closeBtn);
layout->addLayout(btnLayout);
setLayout(layout);
//信号和槽函数
connect(connectBtn,&QPushButton::clicked,[=](){
//获取ip和顿口
QString ip = ipEdit->text();
quint16 port = portEdit->text().toInt();
socket->connectToHost(ip,port);
});
connect(sendBtn,&QPushButton::clicked,[=](){
QString msg = sendMsg->toPlainText();
socket->write(msg.toUtf8().data());
});
//接收到新消息
connect(socket,&QTcpSocket::readyRead,this,[=](){
QByteArray data = socket->readAll();
recvMsg->append(QString(data));
});
}
|
2、服务端ServerWindow.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 | ServerWindow::ServerWindow(QWidget *parent) : QWidget(parent) {
//设置大小
setFixedSize(600, 600);
//设置标题
setWindowTitle("服务器:6666");
//创建布局
QVBoxLayout *layout = new QVBoxLayout;
recvMsg = new QTextEdit;
sendMsg = new QTextEdit;
recvMsg->setEnabled(false);
QHBoxLayout *btnLayout = new QHBoxLayout;
QPushButton *sendBtn = new QPushButton("发送");
QPushButton *closeBtn = new QPushButton("关闭");
layout->addWidget(recvMsg);
layout->addWidget(sendMsg);
btnLayout->addWidget(sendBtn);
btnLayout->addWidget(closeBtn);
layout->addLayout(btnLayout);
setLayout(layout);
//初始化socket
initSocket();
connect(sendBtn,&QPushButton::clicked,[=](){
QString msg = sendMsg->toPlainText();
socket->write(msg.toUtf8().data());
});
}
ServerWindow::~ServerWindow() {
}
//初始化socket
void ServerWindow::initSocket() {
//创建socket
server = new QTcpServer(this);
//监听
server->listen(QHostAddress::Any, 6666);
//连接上的信号和槽函数
connect(server, &QTcpServer::newConnection, this, &ServerWindow::clientConnectToServer);
}
//连接上的信号和槽函数
void ServerWindow::clientConnectToServer() {
//保存通信套接字
socket = server->nextPendingConnection();
//获取连接的ip和端口
QString ip = socket->peerAddress().toString();
int port = socket->peerPort();
//写入
recvMsg->append(QString("[%1:%2]连接成功").arg(ip).arg(port));
//监听新消息
connect(socket,&QTcpSocket::readyRead,this,&ServerWindow::receiveMsg);
}
//有新消息
void ServerWindow::receiveMsg(){
QByteArray data = socket->readAll();
recvMsg->append(QString(data));
}
|
2. udp通信
udp通信不需要连接服务端操作
1、客户端ClientWindow.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 | ClientWindow::ClientWindow(QWidget *parent) : QWidget(parent) {
socket = new QUdpSocket(this);
//设置大小
setFixedSize(600, 600);
//设置标题
setWindowTitle("客户端:8888");
//创建布局
QVBoxLayout *layout = new QVBoxLayout;
QHBoxLayout *hl = new QHBoxLayout;
QFormLayout *fl = new QFormLayout;
QLineEdit *ipEdit = new QLineEdit;
QLineEdit *portEdit = new QLineEdit;
ipEdit->setText("127.0.0.1");
portEdit->setText("6666");
QPushButton *connectBtn = new QPushButton("连接");
fl->addRow("服务器 ip:", ipEdit);
fl->addRow("服务器端口:", portEdit);
hl->addLayout(fl);
hl->addWidget(connectBtn);
QTextEdit *recvMsg = new QTextEdit;
QTextEdit *sendMsg = new QTextEdit;
recvMsg->setEnabled(false);
QHBoxLayout *btnLayout = new QHBoxLayout;
QPushButton *sendBtn = new QPushButton("发送");
QPushButton *closeBtn = new QPushButton("关闭");
layout->addLayout(hl);
layout->addWidget(recvMsg);
layout->addWidget(sendMsg);
btnLayout->addWidget(sendBtn);
btnLayout->addWidget(closeBtn);
layout->addLayout(btnLayout);
setLayout(layout);
socket->bind(8888, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
connect(sendBtn, &QPushButton::clicked, [=]() {
QString ip = ipEdit->text();
int port = portEdit->text().toInt();
QString msg = sendMsg->toPlainText();
socket->writeDatagram(msg.toUtf8(),QHostAddress(ip),port);
});
}
|
2、服务端ServerWindow.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 | ServerWindow::ServerWindow(QWidget *parent) : QWidget(parent) {
socket = new QUdpSocket(this);
//设置大小
setFixedSize(600, 600);
//设置标题
setWindowTitle("客户端:6666");
//创建布局
QVBoxLayout *layout = new QVBoxLayout;
QHBoxLayout *hl = new QHBoxLayout;
QFormLayout *fl = new QFormLayout;
QLineEdit *ipEdit = new QLineEdit;
QLineEdit *portEdit = new QLineEdit;
ipEdit->setText("127.0.0.1");
portEdit->setText("8888");
QPushButton *connectBtn = new QPushButton("连接");
fl->addRow("服务器 ip:", ipEdit);
fl->addRow("服务器端口:", portEdit);
hl->addLayout(fl);
hl->addWidget(connectBtn);
QTextEdit *recvMsg = new QTextEdit;
QTextEdit *sendMsg = new QTextEdit;
recvMsg->setEnabled(false);
QHBoxLayout *btnLayout = new QHBoxLayout;
QPushButton *sendBtn = new QPushButton("发送");
QPushButton *closeBtn = new QPushButton("关闭");
layout->addLayout(hl);
layout->addWidget(recvMsg);
layout->addWidget(sendMsg);
btnLayout->addWidget(sendBtn);
btnLayout->addWidget(closeBtn);
layout->addLayout(btnLayout);
setLayout(layout);
socket->bind(6666, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
connect(socket, &QUdpSocket::readyRead, [=]() {
// QString msg = socket->readAll();
QByteArray data;
data.resize(socket->pendingDatagramSize());
socket->readDatagram(data.data(), data.size());
qDebug() << "接收到消息" << data << endl;
socket->close();
});
}
|