本文有很多c语言代码,客户端是在qt上完成,里面涉及的socket编程大多都是c构建的。因为我也是初学者,对于初学者很容易理解。至于服务端完全有c代码写成直接可以运行,当然还涉及到简单数据库(mysql)。
网络聊天室:
简介:基于Qt界面,和网络协议Udp,Mysql数据库,实现用户的注册与登录,和消息的收发,文件的传输。
1. MYsql数据库的建立(用于存储用户名,和密码)。
2.服务器的搭建:采用UDP传输控制协议,实现对不同种类的消息(如注册,登录,聊天,退出),分类处理。对登录和注册信息,与数据库建立连接,实时查找,和插入数据。用多线程处理,收发消息的同步。多客户时,对客服端的消息对每个客服端进行广播实现多人聊天。
3.客服端的搭建:用Qt搭建,图形界面的工程,多层窗口。对各种消息的种
类进行分类。处理图形界面获取的文本信息,通过网络发给服务器,显示服务器转发多人聊天信息。
4. 在聊天主窗口上安置文件传输按钮,绑定信号与槽函数。发送端获取本地文件路径和文件名,文件名传输采用UDP广播来实现。当收到客服端同意接收的信号后,服务器端对文件进行读操作,存入缓存区通过TCP发送给指定地址。当有消息到客户端时触发槽函数,读入缓存区,写进文件,文件传输完成。
5.进行多人聊天,和文件传输。
注册界面:
聊天主界面:
文件收发界面:
Qt-1
dialog.h
dialog.cpp
#ifndef DIALOG_H
#define DIALOG_H
#include<QLineEdit>
#include <QDialog>
#include<QUdpSocket>
#include<QtNetwork>
#include"thread.h"
typedef struct
{
char type;
char name[32];
char ps[20];
char text[256];
}MSG;
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
QUdpSocket *sender; //sender = new QUdpSocket(this);
QHostAddress serverAddress ;//= QHostAddress("127.0.0.1");
QTimer *timer;
Thread *a;
private slots:
void connected();
void getIp();
void gettime();
void recvmessage(char *b);
void reg();
private:
Ui::Dialog *ui;
signals:
void qu();
};
#endif // DIALOG_H
#include "dialog.h"
#include "ui_dialog.h"
#include <QDebug>
#include<QString>
#include"form.h"
#include<QLineEdit>
#include<QByteArray>
#include<QMessageBox>
#include<QDateTime>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<signal.h>
#include"widget.h"
#include <server.h>
#include <client.h>
MSG tmp;
MSG msg;
int socked;
socklen_t addr_len;
struct sockaddr_in server_addr;
Dialog::Dialog(QWidget *parent) : QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
this->setWindowTitle (tr("网络聊天室"));
if((socked=socket (AF_INET,SOCK_DGRAM,IPPROTO_UDP))<0)
{
perror("socked:");
exit(1);
}
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("192.168.71.115");
server_addr.sin_port = htons(8888);
addr_len = sizeof(server_addr);
timer = new QTimer(this);
connect((QObject*)timer, SIGNAL(timeout()), this, SLOT(gettime()));
timer->start(1000);
a=new Thread;
a->flag=1;
a->start ();
connect (a,SIGNAL(ok(char*)),this,SLOT(recvmessage(char*)));
connect (this,SIGNAL(qu()),a,SLOT(quit()));
getIp();
gettime ();
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::connected ()
{
QString f=ui->lineEdit->text ();
QString b=ui->lineEdit_2->text ();
QByteArray c=f.toLatin1 ();
QByteArray d=b.toLatin1 ();
char *ch=c.data ();
char *ca=d.data ();
memcpy(msg.name,ch,c.length ());
msg.name[c.length ()] = 0;
memcpy(msg.ps,ca,d.length ());
msg.ps[d.length ()] = 0;
msg.type='L';
memset(msg.text,0,sizeof(msg.text));
QMessageBox box;
box.setWindowTitle (tr("错误"));
if(f.length()==0)
{
box.setText(tr("请输入用户名"));
box.exec();
}
else if(b.length()==0)
{
box.setText(tr("请输入密码"));
box.exec();
}
if(sendto(socked,&msg,sizeof(msg),0,(struct sockaddr*)&server_addr,addr_len) < 0)
{
perror("sendto3");
exit(-1);
}
ui->lineEdit->clear ();
ui->lineEdit_2->clear ();
}
void Dialog::recvmessage (char *b)
{
if(memcmp(((MSG*)b)->text,"hello",5)==0)
{
QMessageBox box;
box.setWindowTitle (tr("错误"));
box.setText(tr("帐号或密码错误"));
box.exec();
return;
}
else
{
a->flag=0;
tmp=msg;
emit qu();
a->disconnect (this,SLOT(recvmessage(char*)));
this->close ();
Form *test = new Form;
test->show();
}
}
void Dialog::reg ()
{
MSG b;
b.type='A';
sendto(socked,&b,sizeof(b),0,(struct sockaddr*)&server_addr,addr_len);
a->flag=0;
a->disconnect (this,SLOT(recvmessage(char*)));
emit qu();
this->close ();
Widget *test = new Widget;
test->show();
}
void Dialog::getIp()
{
QList<QHostAddress> list = QNetworkInterface::allAddresses();
foreach (QHostAddress address, list)
{
if(address.protocol() == QAbstractSocket::IPv4Protocol) //我们使用IPv4地址
{
if(address.toString().contains("192.168.1")||address.toString().contains("127.0"))
continue;
//qDebug()<<"本机Ip:"<<address.toString();
//return address.toString();
ui->label_4->setText ("本机IP:"+address.toString ());
}
}
//return 0;
}
void Dialog::gettime ()
{
QDateTime time;
QString timeStr = time.currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
QByteArray a=timeStr.toLocal8Bit ();
ui->label_5->setText(a);
}
from.h
#ifndef FORM_H
#define FORM_H
#include <QWidget>
#include<QLineEdit>
#include <QDialog>
#include<QUdpSocket>
#include<QtNetwork>
#include"thread.h"
namespace Ui {
class Form;
}
class Form : public QWidget
{
Q_OBJECT
public:
explicit Form(QWidget *parent = 0);
~Form();
QUdpSocket *sender; //sender = new QUdpSocket(this);
QHostAddress serverAddress ;//= QHostAddress("127.0.0.1");
QTimer *timer;
Thread *b;
void closeEvent (QCloseEvent *);
private slots:
void sendmessage();
void recvmessage(char *a);
void cleansend();
void getIp();
void gettime();
void autoScroll();
void on_SendFile_clicked();
void on_recevFile_clicked();
public:
Ui::Form *ui;
};
#endif // FORM_H
from.cpp
#include "form.h"
#include "ui_form.h"
#include<QTextCodec>
#include<QTextEdit>
#include"dialog.h"
#include<QMessageBox>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<QTimer>
#include"thread.h"
#include <server.h>
#include <client.h>
Form::Form(QWidget *parent) :
QWidget(parent),
ui(new Ui::Form)
{
//QTextCodec::setCodecForTr(QTextCodec::codecForName("utf8"));
ui->setupUi(this);
timer = new QTimer(this);
connect((QObject*)timer, SIGNAL(timeout()), this, SLOT(gettime()));
timer->start(1000);
getIp ();
b=new Thread;
connect (b,SIGNAL(ok(char*)),this,SLOT(recvmessage(char *)));
b->flag=1;
b->start ();
}
void Form::sendmessage ()
{
autoScroll();
extern MSG msg;
extern int socked;
extern struct sockaddr_in server_addr;
extern socklen_t addr_len;
//QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf8"));
QString talkMsg = ui->textEdit->toPlainText();
QByteArray c=talkMsg.toLocal8Bit ();
char *ch=c.data ();
memcpy(msg.text,ch,c.length ());
msg.text[c.length ()] = 0;
msg.type='B';
QMessageBox box;
box.setWindowTitle (tr("错误"));
if(talkMsg.length()==0)
{
box.setText(tr("发送信息不能为空"));
box.exec();
}
else
{
if(sendto(socked,&msg,sizeof(msg),0,(struct sockaddr*)&server_addr,addr_len) < 0)
{
perror("sendto2");
exit(-1);
}
ui->textEdit->clear ();
ui->textEdit->setFocus ();
}
}
void Form::recvmessage (char *a)
{
switch(((MSG*)a)->type)
{
case 'L':
ui->textBrowser->insertPlainText ("the ");
ui->textBrowser->insertPlainText (((MSG*)a)->name);
ui->textBrowser->insertPlainText (" login");
ui->textBrowser->insertPlainText ("\n");
autoScroll();
break;
case 'B':
ui->textBrowser->insertPlainText (((MSG*)a)->name);
ui->textBrowser->insertPlainText (" 说:");
ui->textBrowser->insertPlainText (((MSG*)a)->text);
ui->textBrowser->insertPlainText ("\n");
autoScroll();
break;
case 'Q':
ui->textBrowser->insertPlainText (((MSG*)a)->name);
ui->textBrowser->insertPlainText (" 退出");
ui->textBrowser->insertPlainText ("\n");
autoScroll();
break;
}
}
void Form::autoScroll() //设置滚屏
{
QTextCursor cursor = ui->textBrowser->textCursor();
cursor.movePosition(QTextCursor::End);
ui->textBrowser->setTextCursor(cursor);
}
void Form::closeEvent (QCloseEvent *)
{
extern MSG tmp;
extern int socked;
extern struct sockaddr_in server_addr;
extern socklen_t addr_len;
tmp.type='Q';
qDebug ("name:%s",tmp.name);
if(sendto(socked,&tmp,sizeof(tmp),0,(struct sockaddr*)&server_addr,addr_len) < 0)
{
perror("sendto2");
exit(-1);
}
qDebug("close");
}
void Form::getIp()
{
QList<QHostAddress> list = QNetworkInterface::allAddresses();
foreach (QHostAddress address, list)
{
if(address.protocol() == QAbstractSocket::IPv4Protocol) //我们使用IPv4地址
{
if(address.toString().contains("192.168.1")||address.toString().contains("127.0"))
continue;
//qDebug()<<"本机Ip:"<<address.toString();
//return address.toString();
ui->label->setText ("本机IP:"+address.toString ());
}
}
//return 0;
}
void Form::gettime ()
{
QDateTime time;
QString timeStr = time.currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
QByteArray a=timeStr.toLocal8Bit ();
ui->label_2->setText(a);
}
void Form::cleansend()
{
ui->textEdit->clear ();
ui->textEdit->setFocus ();
}
Form::~Form()
{
delete ui;
}
void Form::on_SendFile_clicked()
{
Server *file = new Server;
file->setWindowTitle("Server");
file->show();
}
void Form::on_recevFile_clicked()
{
Client *File = new Client;
File->setWindowTitle("Client");
File->show();
}
thread.h
#ifndef THREAD_H
#define THREAD_H
#include <QThread>
#include <QtGui>
#include <QUdpSocket>
class Thread : public QThread
{
Q_OBJECT
public:
Thread();
~Thread();
int flag;
protected:
void run();
int exec ();
signals:
void ok(char *a);
void qu();
private:
private slots:
};
#endif // THREAD_H
thread.cpp
#include "thread.h"
#include "dialog.h"
#include <QObject>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include"form.h"
Thread::Thread()
{
flag=0;
}
void Thread::run()
{
qDebug("thread run");
MSG a;
extern int socked;
extern struct sockaddr_in server_addr;
extern socklen_t addr_len;
while(flag)
{
if(recvfrom(socked,&a,sizeof(a),0,(struct sockaddr*)&server_addr,&addr_len) < 0)
{
perror("recvfrom");
exit(-1);
}
emit ok((char *)&a);
qDebug ("the data is coming");
qDebug ("rev1111:%s",a.text);
this->sleep (1);
}
}
Thread::~Thread ()
{
qDebug ("quit\n");
}
文件收发代码在上一博客,本文不再累赘.
服务代码及检测包: