现在的位置: 首页 > 综合 > 正文

Qt 聊天程序服务器端

2018年03月21日 ⁄ 综合 ⁄ 共 7641字 ⁄ 字号 评论关闭

聊天程序:

   QT实现的界面

   网络的数据通信

 

   服务器端:

       建立用户UI

              建立服务器socket

              接受客户连接

              为每个各户建立线程处理客户数据

 

 设计界面

 QMainWindow 增加:菜单,工具条,状态条

 菜单:

     QMenuBar

         addMenu

     QMenu

         addAction

     QMenuItem/QAction

           构造器

     菜单的响应

状态条

   QStatusBar

 

 

chatServer

 

 

charServer.cpp

#include<QApplication>

#include “ServerWindow.h”

#include<QTextCodec>

int  main(int  args , char ** argv)

{

     QApplication   app(args , argv);

     QTextCodec * codec=QTextCodec::codecForName(“utf-8”);

     QTextCodec::setCodecForTr(codec);

     ServerWindow  sw;

     return  app.exec();

}

 

 

charServer.pro

 

TEMPLATE=app

SOURCES=charServer.cpp \

ServerWindow.cpp \

chatException.cpp \

ServerSocket.cpp \

ThAccept.cpp \

ThClient.cpp

HEADERS=ServerWindow.h chatException.hServerSocket.h ThAccept.h ThClient.h

CONFIG=release qt

QT=core gui

TARGET=charServer

 

 

 

ServerWindow.h

 

#ifndef SERVER_WINDOW_H

#define SERVER_WINDOOW_H

#include<QMainWindow>

#include<QWidget>

#include<QTextEdit>

#include<QMenuBar>

#include<QMenu>

#include<QAction>

#include<QStatusBar>

#include<QLabel>

#include “ThAccept.h”

#include<list>

#include “ThClient.h”

using namespace std;

 

 

class ServerWindow :public QMainWindow

{

Q_OBJECT

public:

    static  list<ThClient*>allusers;

 private:

     QTextEdit *info;

     //菜单

     QMenuBar * bar;

     QMenu *mnuserver;

     QAction  *actstart;

     QAction  *actexit;

     //状态条

     QStatusBar *status;

     QLabel *lbltip;

     QLabel *lblresult;

     QLabel *lbltim;

     //接收线程

     ThAccept  thaccept;

 public:

     ServerWindow(QWidget *p=NULL);

 public slots:

      void  onStart();    //菜单点击的槽函数

};

#endif

 

 

ServerWindow.cpp

 

#include “ServerWindow.h”

#include<QColor>

#include<QMessageBox>

#include “ChatException”

 

list<ThClient*>  ServerWindow::allusers;

void ServerWindow::onStart()

{

     //QMessageBox::information(this,tr(“提示”),tr(“响应”));

    try

     {

         thaccept.init();

         thaccept.info=info;

         info->setTextColor(QColor(0,255,0));

         info->append(tr(“服务器启动成功!”));

         connect(&thaccept , SIGNAL(sigInfo(const QString &)) ,

info,SLOT(append(const QString&)));

         thaccept.start();

         info->append(tr(“服务器接收线程启动!”));

     }

     catch(ChatException e)

     {

          info->setTextColor(QColor(255,0,0));

          info->apped(tr(e.what()));

     }

}

 

ServerWindow::ServerWindow(QWidget*p):QMainWindow(p)

{

     //初始化窗体

     this->resize(1366,768);

     this->move(0,0);

     this->setWindowTitle(tr(“聊天服务器”));

     //初始化组件

     info = new QTextEdit;

     info->setTextColor(QColor(255,0,0));

     info->append(tr(“欢迎使用聊天程序”));

     info->append(tr(“===============”));

     info->setTextColor(QColor(0,255,255));

     info->setFontPointSize(20);

     this->setCentralWidget(info);   //设置窗体的中间组件

     // 初始化菜单

     bar = new QMenuBar(this);

     mnuserver = new QMenu(tr(“服务器”),bar);

     actstart= new QAction(tr(“启动服务器”),mnuserver);

     actexit = new QAction(tr(“退出”),mnuserver);

     //菜单关系维护

     mnuserver->addAction(actstart);

     mnuserver->addSeparator();     //菜单添加分割条

     mnuserver->addAction(actexit);

     bar->addMenu(mnuserver);

     this->setMenuBar(bar);

     

     //初始化状态条

     status = new QStatusBar(this);

     lbltip = new QLabel(tr(“提示”),status);

      lblresult = new QLabel(tr(“操作结果显示”),status);

     lbltim = new QLable(tr(“2010-11-24”),status);

     lbltim->setFrameShape(QFrame::Panel);   //设置边框

     //维护关系

     status->addPermanentWidget(lbltip,300);     //300为最小的大小

     status->addPermanentWidget(lblresult,500);

     status->addPermanentWidget(lbltim,0);      //0为默认剩余大小

     this->setStatusBar(status);

     connect(actstart , SIGNAL(triggered) ,

this,SLOT(onStart()));

     this->setVisible(true);

    

 

}

 

//异常类

chatException.h

#ifndef  CHAT_EXCEPTION_H

#define CHAT_EXCEPTION_H

 

#include<exception>

using namespace std;

 

class ChatException :public  exception

{

 private:

      char  msg[50];    //错误信息的描述

 public:

     ChatException();

     ChatException(const char *);

     const char * what() const throw();

};

#endif

 

 

chatException.cpp

 

#include “chatException.h”

#include<cstdlib>

#include<cstring.h>

#include<cstdio>

using namespace std;

 

ChatException::CharException()

{

      memset(msg,0,sizeof(msg));

      sprintf(msg, “聊天异常!”);

}

 

ChatException::CharException(const char *m)

{

      memset(msg,0,sizeof(msg));

      sprintf(msg, “聊天异常:%s”,m);

 

}

 

const char * ChatException::what() const throw()

{

      return  msg;

}

 

ServerSocket.h

 

#ifndef SERVER_SOCKET_H

#define SERVER_SOCKET_H

 

#include<QObject>

#include “chatException.h”

class ServerSocket : public QObject

{

Q_OBJECT

 public:

      char ip[30];

      short port;

      int fd;

 public:

     void initSocket() throw (ChatException);

     int accept() throw(ChatExceotion);

};

#endif

 

 

ServerSocket.cpp

 

#include “ServerSocket.h”

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

#include<unistd.h>

 

void ServerSocket::initSocket() throw(ChatException)

{

     struct  sockaddr_in addr;

    int  r;

     fd=socket(AF_INET,SOCK_STREAM,0);

    if(fd== -1) throw ChatException(“socket错误”);

    addr.sin_family=AF_INET;

    addr.sin_port=htons(port);

    addr.sin_addr.s_addr=inet_addr(ip);

    

    r=bind(fd,(struct sockaddr*)&addr,sizeof(addr));

     if(r== -1)

    {

        close(fd);

throw ChatException(“bind错误”);

    }

    r=listen(fd,10);

    if(r == -1)

    {

          close(fd);

throw ChatException(“listen 错误”);

    }

    

}

 

int ServerSocket::accept()throw(ChatExceotion)

{

     int  cfd;

     cfd=::accept(fd,NULL,0);

     if(cfd == -1) throw ChatException(“accept错误”);

     return cfd;

}

 

ThAccept.h

 

#ifndef  TH_ACCEPT_H

#define  TH_ACCEPT_H

#include<QThread>

#include “ChatException.h”

#include “ServerSocket.h”

#include <QTextEdit>

class ThAccept :public QThread,public QObject

{

Q_OBJECT

 public:

     QTextEdit *info;

 private:

    ServerSocket  server;

 public:

    void  init() throw(ChatException);

    void  run();  //在线程中接收客户连接

 public: signal:

     void sigInfo(const QString &);

  

};

#endif

 

 

 

ThAccept.cpp

 

#include “ThAccpet.h”

#include<cstdio>

#include “ThClient.h”

#include “ServerWindow.h”

using namespace  std;

 

void ThAccept::init() throw(ChatException)

{

       sprintf(server.ip,  “%s”,“127.0.0.1”);

       server.port=8888;

       try

       {

           Server.initSocket();

       }

       catch(ChatException e)

       {

              throw e;

       }

}

void ThAccept::run()

{

       while(true)

       {

            try

            {

                   int  fd=server.accept();

                    //发出信号

                    emit  sigInfo(tr(“有人连接!”));

                    //建立子线程监听对应客户

                    ThClient  *th=new ThClient ;

                    th->fd=fd;

                    ServerWindow::alluser.push_back(th);

                    connect(th ,SIGNAL(sigInfo(const QString&)),

info,SLOT(append(const QString&)));

                    th->start();

              }

              catch(ChatException e)

              {

                   //发出信号

                   emit sigInfo(tr(“服务器崩溃!”));

                   break;

              }

       }

}

 

 

 

ThClient.h

#ifnedf TH_CLIENT_H

#define TH_CLIENT_H

#include<QThread>

class  ThClient : public QThread

{

Q_OBJECT

public:

  int  fd;

  void   run();  //接收客户数据,广播

public:signals:

       void  sigInfo(const QString&);

};

#endif

 

 

 

ThClient.cpp

 

#include “ThClient.h”

#include<sys.socket.h>

#include<list>

#include “ServerWindow.h”

#include<unistd.h>

using namespace  std;

 

void ThClient::run()

{

      int  r;

      char buf[1024];

      while(true)

      {

            r=recv(fd , buf ,sizeof(buf)-1,0);

            if(r<=0)

            {

                  //emit

                  emit  sigInfo(tr(“有客户退出!”));

                  ServerWindow::alluser.remove(this);

                  close(fd);

                //  delete this;

break;

            }

            buf[r]= ‘\n’;

            //发送消息,把接收数据显示服务器主窗体

            emit sigInfo(tr(buf));

            //广播

            list<ThClient*>::iterator it= ServerWindow::allusers.begin();

            while(it!=ServerWindow::allusers.end())

            {

                   send((*it)->fd , buf ,strlen(buf),0);

                   it++;

            }  

      }

}

 

 

 

 

抱歉!评论已关闭.