基于UDP协议的socket编程

一、socket概述

1.socket一般被称为“套接字”,网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端就叫做socket。

2.建立网络通信连接至少需要一个端口号(socket),socket利用网络之间的通信设施实现进程通信,但它对通信设施的细节不关心,只要通信设施能够提供足够的通信能力,就可以实现通信。

例子:假如你想给你一个人打电话,首先你得有一部电话机,这个电话机就相当于申请了一个socket;同时你也要知道对方的电话号码,就相当于对方也有了一个固定的socket;然后你拨号呼叫对方,相当socket发出连接请求,如果对方在并且空闲,就会接起电话,双方就可以正式通话,相当于连接成功;双方通话的这个过程,就相当于向socket发送数据和从socket接收数据的过程。

基于UDP协议的socket编程

3. socket常用函数

网络连接函数:① socket():创建套接字;

                        ② bind():绑定本机端口;

                        ③ connect():与端口建立连接;

                        ④ listen():监听端口是否有数据请求过来;

                        ⑤ accept():接受数据的请求连接;

                        ⑥ recvfrom() :数据接受;

                        ⑦ send,sendto():数据发送;

                        ⑧ close():关闭套接字。

4.socket编程步骤

(1)服务器端步骤

    ①使用socket()函数加载套接字库,创建套接字;

    ②使用bind()函数来绑定套接字到一个IP地址和一个端口上;

    ③使用Listen()函数将套接字设置为监听模式,等待连接请求;

    ④用accept()函数接受连接请求,返回一个新的对应于连接的套接字;

    ⑤用send()/sendto()函数返回的套接字和客户端进行通信;

    ⑥返回到第三步,等待另一个请求;

    ⑦用closesocket()函数关闭套接字。

(2)客户端步骤

    ①使用socket()函数加载套接字库,创建套接字

    ②使用connect()函数向服务器发出连接请求;

    ③用send()/recv()函数与服务器端进行通信;

    ④通信完成后,用closesocket()函数关闭套接字。

二、UDP协议

1.  UDPUserDatagram Protocol 的简称,中文名是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。它不与对方建立连接,而是直接就把数据报发送过去。

2. UDP协议是面向非连接的协议,没有建立连接的过程,所以它的通信效率高;也正因为如此,它的可靠性不如TCP协议高。UDP只适用于一次只传送少量数据、对可靠性要求不高的应用环境,一次只能发送的数据不能超过64KB 。

3.UDP协议流程图

                                                                                                                 服务器端

基于UDP协议的socket编程

因为UDP是无连接的 ,所以服务器端并不需要listen()函数和accept()函数。

4. UDP协议的优点

UDP套接口是无连接的,不可靠的数据报协议,既然它是不可靠的,为什么还要用呢?我总结以下三点:

(1)UDP协议支持广播或多播;

(2)因为它是无连接的,所以处理速度快;

(3)可以设置超时防止对方无限等待。

三、QT实现

1. 页面的搭建

基于UDP协议的socket编程

服务器端和客户端的页面是一样的,都是由输入款、输出框和发送按钮三部分组成的。

2. 服务器端代码实现

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QVariant>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    serverudp=new QUdpSocket(this);
    //绑定读数据端口(监听端口),允许其他服务绑定到此端口
    serverudp->bind(5000,QUdpSocket::ShareAddress);
    connect(serverudp,SIGNAL(readyRead()),this,SLOT(recv()));
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::recv()
{
    while(serverudp->hasPendingDatagrams())
    {
        QByteArray data;
        data.resize(serverudp->pendingDatagramSize());
        serverudp->readDatagram(data.data(),data.size());
        ui->textEdit_show->clear();
        ui->textEdit_show->setText(QVariant(data).toString());
    }
}
void MainWindow::on_pushButton_clicked()
{
    serverudp->writeDatagram(QVariant(ui->textEdit_write->toPlainText()).toByteArray(),QHostAddress::LocalHost,10000);
}

2. 客户端代码实现

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTextCodec>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    clientudp=new QUdpSocket(this);
    //绑定读数据端口(监听端口),允许其他服务绑定到此端口
    clientudp->bind(10000,QUdpSocket::ShareAddress);
    connect(clientudp,SIGNAL(readyRead()),this,SLOT(recv()));
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::on_pushButton_clicked()
{
    clientudp->writeDatagram(QVariant(ui->textEdit_write->toPlainText()).toByteArray(),QHostAddress::LocalHost,5000);
}
void MainWindow::recv()
{
    while(clientudp->hasPendingDatagrams())
    {
        QByteArray data;
        data.resize(clientudp->pendingDatagramSize());
        clientudp->readDatagram(data.data(),data.size());
        ui->textEdit_show->setText(QVariant(data).toString());
    }
}

3. 功能实现

基于UDP协议的socket编程

在客户端的输入框输入hello world,在服务器端的输出框就接收到了hello world,同样也可以在服务器上的输入端给客户端发送数据,两个是互通的。

四、总结

通过这次对Socket编程的学习,我对socket编程有了一个大致的,初步实现了UDP形式的客户端与服务器端的通信。在实现功能的时候,我总结了必须要掌握的以下几点知识:

(1)清楚地掌握socket编程步骤;

(2)掌握UDP协议的原理和实现步骤;

(3)能够区分在无连接UDP方式下和有连接方式TCP下的socket编程;

(4)掌握QT开发软件的使用。