一、socket概述
1.socket一般被称为“套接字”,网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端就叫做socket。
2.建立网络通信连接至少需要一个端口号(socket),socket利用网络之间的通信设施实现进程通信,但它对通信设施的细节不关心,只要通信设施能够提供足够的通信能力,就可以实现通信。
例子:假如你想给你一个人打电话,首先你得有一部电话机,这个电话机就相当于申请了一个socket;同时你也要知道对方的电话号码,就相当于对方也有了一个固定的socket;然后你拨号呼叫对方,相当socket发出连接请求,如果对方在并且空闲,就会接起电话,双方就可以正式通话,相当于连接成功;双方通话的这个过程,就相当于向socket发送数据和从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. UDP是UserDatagram Protocol 的简称,中文名是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。它不与对方建立连接,而是直接就把数据报发送过去。
2. UDP协议是面向非连接的协议,没有建立连接的过程,所以它的通信效率高;也正因为如此,它的可靠性不如TCP协议高。UDP只适用于一次只传送少量数据、对可靠性要求不高的应用环境,一次只能发送的数据不能超过64KB 。
3.UDP协议流程图
服务器端
因为UDP是无连接的 ,所以服务器端并不需要listen()函数和accept()函数。
4. UDP协议的优点
UDP套接口是无连接的,不可靠的数据报协议,既然它是不可靠的,为什么还要用呢?我总结以下三点:
(1)UDP协议支持广播或多播;
(2)因为它是无连接的,所以处理速度快;
(3)可以设置超时防止对方无限等待。
三、QT实现
1. 页面的搭建
服务器端和客户端的页面是一样的,都是由输入款、输出框和发送按钮三部分组成的。
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. 功能实现
在客户端的输入框输入hello world,在服务器端的输出框就接收到了hello world,同样也可以在服务器上的输入端给客户端发送数据,两个是互通的。
四、总结
通过这次对Socket编程的学习,我对socket编程有了一个大致的,初步实现了UDP形式的客户端与服务器端的通信。在实现功能的时候,我总结了必须要掌握的以下几点知识:
(1)清楚地掌握socket编程步骤;
(2)掌握UDP协议的原理和实现步骤;
(3)能够区分在无连接UDP方式下和有连接方式TCP下的socket编程;
(4)掌握QT开发软件的使用。