@[TOC]Linux+QT搭建简易登录注册系统
这里简单讲一下,Linux操作系统中TCP服务器的搭建流程,这里直接上一张图
一.TCP网络服务器编程
1. int sockfd = socket()
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int socket(int domain, int type, int protocol);
函数参数:
domain:协议族 AF_INET : IPv4 Internet protocols
type: 套接字类型 SOCK_STREAM : 流式套接字
protocol:0
函数功能:
创建通信节点
返回值:
成功:非负的文件描述符,即套接字
失败:-1,并且设置errno的值,使用perror()函数查看errno对应的错误信息
通用地址结构
"/usr/include/linux/socket.h"
struct sockaddr
{
u_short sa_family; // 地址族, AF_xxx
char sa_data[14]; // 14字节协议地址
};
Internet协议地址结构
" /usr/include/netinet/in.h"
struct sockaddr_in
{
u_short sin_family; // 地址族, AF_INET,2 bytes
u_short sin_port; // 端口,2 bytes
struct in_addr sin_addr; // IPV4地址,4 bytes
char sin_zero[8]; // 8 bytes unused,作为填充
};
IPv4地址结构
// internet address
struct in_addr
{
in_addr_t s_addr; // u32 network address
};
**2. bind();//将服务器的ip地址端口号与socket绑定**
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
函数参数:
sockfd:socket函数的返回值
addr: 服务器地址结构指针
addrlen:服务器地址结构长度
函数功能:
将服务器的ip地址端口号与socket绑定
返回值:
成功:0
失败:-1,并且设置errno的值,使用perror()函数查看errno对应的错误信息
3. listen();//监听是否有客户端发送连接请求
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int listen(int sockfd, int backlog);
函数参数:
sockfd:socket函数的返回值
backlog: 监听队列最大数
函数功能:
监听是否有客户端发送连接请求
返回值:
成功:0
失败:-1,并且设置errno的值,使用perror()函数查看errno对应的错误信息
4.int rws = accept();//阻塞等待客户端连接
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
函数参数:
sockfd:socket函数的返回值
addr: 客户端地址结构指针 可指定为NULL
addrlen:客户端地址结构大小的指针 可指定为NULL
函数功能:
阻塞等待客户端连接
返回值:
成功:通信套接字
失败:-1,并且设置errno的值,使用perror()函数查看errno对应的错误信息
//通信
read(rws,...)/write(rws,...)/recv()/send()
//关闭套接字
close(rws);
close(sockfd);
二.TCP客户端编程
int sockfd = socket();
[bind] 可省略
connect();//给服务器发送连接请求
头文件:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
函数原型:
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
函数参数:
sockfd:socket函数的返回值
addr: 服务器地址结构指针
addrlen:服务器地址结构长度
函数功能:
给服务器发送连接请求
返回值:
成功:0
失败:-1,并且设置errno的值,使用perror()函数查看errno对应的错误信息
//通信
write()/read()/recv()/send()
close();
看到这里,Linux服务器直接上源码
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <strings.h>
#include <time.h>
#include <stdlib.h>
//搭建tcp服务器
int main(void)
{
int sockfd,connfd;
int ret;
sockfd = socket(AF_INET,SOCK_STREAM , 0); //买手机
//如果成功就返回生成的SOCKET,如果失败就返回INVALID_SOCKET(-1)
if(sockfd == -1)
{
perror("socket error");
return 1;
}
//卡 addr
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(5555);
addr.sin_addr.s_addr = inet_addr("0");
ret = bind(sockfd,(struct sockaddr *)&addr,sizeof(addr)); //插卡
//listen函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数。
listen(sockfd,5); //开机
if(listen(sockfd,5) == -1)
{
perror("listen error");
return 1;
}
while(1)
{
connfd = accept(sockfd,NULL,NULL); //接听
if(connfd<0)
{
perror("accpet() failed");
return 1;
}
printf("链接成功\n");
while(1)
{
char buf[256];
char str1[32]; //注册账号
char str2[32]; //注册密码
char str3[32]; //登陆账号
char str4[32]; //登陆密码
//超级用户
char root[255] = "root";
char m[255] = "abc";
bzero(buf,sizeof(buf)); //清空数组
ret = recv(connfd,buf,sizeof(buf),0);
if(ret<=0){
printf("client quit\n");
break;
}
if(strcmp(buf,"1") == 0) {
bzero(str1,sizeof(str1));
bzero(str2,sizeof(str2));
recv(connfd,str1,sizeof(str1),0);
recv(connfd,str2,sizeof(str2),0);
printf("\n注册\n帐号/密码\n%s\n%s\n",str1,str2);
bzero(buf,sizeof(buf));
send(connfd,"s",sizeof("s"),0);
//break;
} else if(strcmp(buf,"2") == 0) {
bzero(str3,sizeof(str3));
bzero(str4,sizeof(str4));
recv(connfd,str3,sizeof(str3),0);
recv(connfd,str4,sizeof(str4),0);
bzero(buf,sizeof(buf));
if(( strcmp(str1,str3) == 0) && (strcmp(str2,str4) == 0) || (strcmp(root,str3) == 0) && (strcmp(m,str4) == 0) )
{
printf("\n登陆成功\n");
send(connfd,"l",sizeof("l"),0);
} else {
printf("\n登陆失败\n");
printf("\n帐号/密码\n%s\n%s\n",str3,str4);
send(connfd,"x",sizeof("x"),0);
}
}
else if(strcmp(buf,"3") == 0){
printf("\n退出\n");
}
}
}
return 0;
}
QT界面设计界面
QT源码设计
login.h
#ifndef LOGIN_H
#define LOGIN_H
#include <QWidget>
#include <QMainWindow>
#include <QTcpSocket>
#include <QDebug>
namespace Ui {
class login;
}
class login : public QWidget
{
Q_OBJECT
public:
explicit login(QWidget *parent = 0);
~login();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
void tcp_recv();
void on_pushButton_3_pressed();
private:
Ui::login *ui;
QTcpSocket *socket;
};
#endif // LOGIN_H
login.cpp
#include "login.h"
#include "ui_login.h"
#include "mainwindow.h"
#include <QLabel>
#include <QMovie>
login::login(QWidget *parent) :
QWidget(parent),
ui(new Ui::login)
{
ui->setupUi(this);
socket = new QTcpSocket;
//设置背景图
QPixmap pixmap = QPixmap(":/picture/6.jpg").scaled(this->size());
QPalette palette(this->palette());
palette.setBrush(QPalette::Background, QBrush(pixmap));
this->setPalette(palette);
//设置label窗口部件动态图
// ui->label->setScaledContents(true);
// QMovie *iconShow = new QMovie(":5.gif");
// ui->label->setMovie(iconShow);
// iconShow->start();
//this->close();
connect(socket,&QTcpSocket::readyRead,this,&login::tcp_recv);
}
login::~login()
{
delete ui;
}
void login::on_pushButton_3_pressed()
{
socket->abort();
socket->connectToHost("192.168.1.30", 5555);
}
void login :: tcp_recv()
{
QByteArray data = socket->readAll();
qDebug()<<"recv:"<<QString(data);
if(0==strcmp(data,"l")){
//this->close();
//MainWindow *fa = new MainWindow();
//this->close();
//fa->show();
}
}
void login::on_pushButton_clicked()
{
//登录功能模块
//实现页面跳转
MainWindow *fa = new MainWindow();
this->close();
fa->show();
QString name = ui->lineEdit->text();
QString pawd = ui->lineEdit_2->text();
char buf[256]="2";
socket->write(buf,sizeof(buf)); //发送注册请求
char data[32];
strcpy(data, name.toLatin1().data());
socket->write(data,32); //发送名字
strcpy(data,pawd.toLatin1().data());
socket->write(data,32); //发送密码
}
void login::on_pushButton_2_clicked()
{
//注册功能模块
QString name = ui->lineEdit->text();//获取用户名
QString pawd = ui->lineEdit_2->text();//获取密码
char buf[256]="1";
socket->write(buf,sizeof(buf)); //发送注册请求
char data[32];
strcpy(data, name.toLatin1().data());
socket->write(data,32); //发送名字
strcpy(data, pawd.toLatin1().data());
socket->write(data,32); //发送密码
socket->read(data,32);
}
运行效果
是不是很完整了呀,点个赞支持一下吧。
我们仍需共生命的慷慨和繁华相爱,即使岁月以刻薄和荒芜相欺。