本项目为本科课程作业,质量有限,仅供参考学习,有问题或建议欢迎与作者交流 VX:Despacitomoonquake
前言
TCP连接:Socket套接字基础知识
TCP(Transmission Control Protocol 传输控制协议)把连接作为最基本的抽象。TCP的许多特性都与TCP是面向连接的这个基本特征有关。因此我们对TCP连接需要有更清楚的了解。 每一条TCP连接有两个端点。
那么TCP连接的端点是什么呢?
一、TCP连接的端点
TCP连接的端点不是主机的IP地址,不是应用进程,也不是运输层的协议端口。 TCP实现两个终端的通信,故除了需要获取目标主机的IP地址外,还需要目标主机的对应应用进程端口号Port, 所以TCP连接的端点叫做套接字(socket)或插口。根据RFC 793定义:端口号拼接到IP地址即构成了套接字 所以TCP使用Socket套接字作为端点。
套接字socket = (IP地址:端口号)
每一条TCP连接唯一的被通信两端的两个端点(即套接字对 socket pair)所确定。即:
TCP连接:: = { socket1,socket2 } = { (IP1, Port1), (IP2, Port2) }
这里IP1和IP2分别是两个端点主机的IP地址,而Port1和Port分别是两个端点主机中的端口号
一种理解是Socket就是该模式的一个实现:即socket是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。
TCP/IP与Socket详解参考资料
二、代码分析
代码架构
(一)头文件
1.client.h
主要include一些库,定义一些函数,创建socket对象 代码如下:
#ifndef CLIENT_H
#define CLIENT_H
#include <QMainWindow>
#include <QTcpSocket>
#include <QKeyEvent>
#include <QWidget>
namespace Ui {
class Client;
}
class Client : public QMainWindow
{
Q_OBJECT
public:
explicit Client(QWidget *parent = nullptr);
~Client();
private slots:
void on_connect_button_clicked(bool checked);
void on_send_button_clicked();
void readyRead_SLOT();
void connected_SLOT();
private:
Ui::Client *ui;
QTcpSocket *socket;
};
#endif
2.server.h
代码如下:
#ifndef SERVER_H
#define SERVER_H
#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QString>
QT_BEGIN_NAMESPACE
namespace Ui { class Server; }
QT_END_NAMESPACE
class Server : public QMainWindow
{
Q_OBJECT
public:
Server(QWidget *parent = nullptr);
~Server();
private slots:
void on_send_button_clicked();
void on_startorstop_Listen_clicked(bool checked);
void readyRead_SLOT();
void newConnection_SLOT();
private:
Ui::Server *ui;
QTcpSocket *socket;
QTcpServer *server;
};
#endif
(二)源文件
1、client.cpp
主要include一些库,定义一些函数,创建socket和server对象
#include "client.h"
#include "ui_client.h"
#include "stdio.h"
#include "QString"
Client::Client(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Client)
{
ui->setupUi(this);
ui->connect_button->setCheckable(true);
socket = new QTcpSocket();
connect(socket,SIGNAL(connected()),this,SLOT(connected_SLOT()));
}
Client::~Client()
{
delete ui;
}
void Client::connected_SLOT()
{
connect(socket,SIGNAL(readyRead()),this,SLOT(readyRead_SLOT()));
}
void Client::readyRead_SLOT()
{
qDebug() << "Client Received!";
QString buffer;
buffer = socket->readAll();
if(!buffer.isEmpty())
{
ui->receiver->appendPlainText(buffer);
}
}
void Client::on_connect_button_clicked(bool checked)
{
if(checked)
{
QString IP = ui->ipnum->text();
int Port = ui->portnum->text().toUInt();
socket->abort();
socket->connectToHost(IP,Port);
if(!socket->waitForConnected(1000))
{
qDebug() << "Connect failed, please try again later!";
ui->connect_button->toggle();
return;
}
qDebug() << "Connect Successfully! Connect with IP:" << IP << "; port:" << Port;
ui->connect_button->setText("断开连接");
ui->send_button->setEnabled(true);
}
else
{
qDebug() << "Disconnect!";
socket->disconnectFromHost();
ui->connect_button->setText("连接");
ui->send_button->setEnabled(false);
}
}
void Client::on_send_button_clicked()
{
qDebug() << "Client Send: " << ui->sender->toPlainText().toLatin1();
socket->write(ui->sender->toPlainText().toLatin1());
socket->flush();
}
2、server.cpp
#include "server.h"
#include "ui_server.h"
Server::Server(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::Server)
{
ui->setupUi(this);
ui->startorstop_Listen->setCheckable(true);
socket = new QTcpSocket();
server = new QTcpServer();
connect(server,SIGNAL(newConnection()),this,SLOT(newConnection_SLOT()));
}
Server::~Server()
{
delete ui;
}
void Server::newConnection_SLOT()
{
socket = server->nextPendingConnection();
connect(socket,SIGNAL(readyRead()),this,SLOT(readyRead_SLOT()));
}
void Server::readyRead_SLOT()
{
qDebug() << "Server Received!";
QString buffer;
buffer = socket->readAll();
if(!buffer.isEmpty())
{
ui->receiver->appendPlainText(buffer);
}
}
void Server::on_startorstop_Listen_clicked(bool checked)
{
if(checked)
{
int port = ui->portnum->text().toUInt();
if(!server->listen(QHostAddress::Any, port))
{
qDebug() << server->errorString();
ui->startorstop_Listen->toggle();
return;
}
qDebug() << "Listen Successfully! Message from port:" << port;
ui->startorstop_Listen->setText("停止监听");
ui->send_button->setEnabled(true);
}
else
{
qDebug() << "Stop Listening!";
if(socket->state() == QAbstractSocket::ConnectedState)
{
socket->disconnectFromHost();
}
server->close();
ui->startorstop_Listen->setText("开始监听");
ui->send_button->setEnabled(false);
}
}
void Server::on_send_button_clicked()
{
qDebug() << "Server Send: " << ui->sender->toPlainText().toLatin1();
socket->write(ui->sender->toPlainText().toLatin1());
socket->flush();
}
3、main.cpp
#include "server.h"
#include "client.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Server w1;
Client w2;
w2.setFocusPolicy(Qt::ClickFocus);
w1.move(320,340);
w2.move(960,340);
w1.show();
w2.show();
return a.exec();
}
(三)UI设计文件
client.ui server.ui 可以手动设计,对应文本框或窗口、按键名与代码保持一致即可。 (如果实在懒得设计想看效果,可以直接下载最下面的源码)
三、总结及源码链接
代码内注释很完整,有待指正,感谢阅读,您的支持是对我最大的帮助! 源代码在这
|