步骤

  1:实例化两个套接字(服务器和客户端的套接字都一样,不用再向TCP一样分serveSocket,TcpSocket)
  2:接收方bind() 自己的端口port,IP
  3:收发
  4:关闭套接字。

TCP与UDP区别

  UDP通信过程中,每次都需要指定数据接收端的IP和端口,和发快递差不多,每次发都要填地址;
TCP则三次握手建立通道后每次发送就不必指定端口和IP了,在通道中就发送了。;和打电话一样,电话一旦接通就随便唠了。
UDP:

udpSocket->writeDatagram(str.toUtf8(),QHostAddress(ip),port);

TCP:

tcpSocket->write(str.toUtf8().data())

从两者的发送可以看出UDP每次发送都要填IP与Port,TCP建立完通道后就不用管了。

  UDP通信不需要建立连接,因此不需要进行 connect() 操作。TCP则又是newconnection 又是connected来确保连接畅通。

  TCP是以字节流的形式传输数据,因此会出现粘包现象,UDP则以数据包的形式传输。

  使用UDP进行通信,服务器和客户端的处理步骤比TCP要简单很多,并且两端是对等的(通信的处理流程几乎是一样的),也就是说并没有严格意义上的客户端和服务器端。但哪一端是接收数据的角色,那么这个接收端就必须绑定(bind)一个固定的端口,因为起码得告诉发数据的人往哪里发吧。如果某一端不需要接收数据,这个绑定操作就可以省略不写了,通信的套接字会自动绑定一个随机端口,并且随着数据发送过去,在接收端recv()函数中会解析出发送者的IP与Port,这样接收者也能给发送者回话了!这点和TCP差不多。不过这种只绑定一端的做法的代价是,绑定方无法给未绑定方发消息,因为绑定方是不知道未绑定方的IP与Port的(未绑定系统随机非配发送端口),也就是说第一次发送的方向是固定的!这点和TCP一样,用TCP协议也基本上默认了第一次发送方向固定这一条件。怎么实现向QQ一样两边谁先发都可以的通信呢?两边都bind()就可以了啊!这样两边的发送地址都固定了,都知道对方的IP,port的情况下,谁先发都可以。

  TCP是一定会完整,准确的发送数据的,粘包可以自己解决!UDP不对收到的数据进行排序,在UDP报文的首部中并没有关于数据顺序的信息,UDP对接收到的数据报不回复确认信息,发送端不知道数据是否被正确接收,也不会重发数据。如果发生了数据丢失,不存在丢一半的情况,如果丢当前这个数据包就全部丢失了。因此,UDP简单,随意的代价就是可能会数据丢失。

代码

附上UDP.cpp代码,客户端和服务器共用一个代码,都bind()了:

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
#include "client.h"
#include "ui_client.h"
#include <QHostAddress>

client::client(QWidget *parent) :
QWidget(parent),
ui(new Ui::client)
{
ui->setupUi(this);
udpSocket = new QUdpSocket(this);
udpSocket->bind(8887);
setWindowTitle("端口8887");
connect(udpSocket,&QUdpSocket::readyRead,this,&client::dealMsg);

}

client::~client()
{
delete ui;
}

void client::dealMsg()
{
char buf[ 1024 ]={0};
QHostAddress cliAddr;
quint16 port;
qint64 len =udpSocket->readDatagram(buf, sizeof(buf),&cliAddr, &port);
if(len>0)
{
QString str = QString("{%1:%2} %3")
.arg(cliAddr.toString())
.arg(port)
.arg(buf);
ui->textEdit->setText(str);
}
}
void client::on_Buttonsend_clicked()
{
QString ip = ui->lineIP->text();
qint16 port = ui->lineport->text().toInt();
QString str =ui->textEdit->toPlainText();
udpSocket->writeDatagram(str.toUtf8(),QHostAddress(ip),port);

}