一.聊天程序
QT实现的界面
网络的数据通信
服务器端
建立用户UI
建立服务器socket
接受客户连接
为每个各户建立线程处理客户数据
分析设计的一般规律:
1.用例
2.事件流
3.找对象,并且抽象类
4.设计类本身
5.设计类关系(泛化关系,关联关系)
6.设计模式优化设计
设计界面
QMainWindow增加:菜单,工具条,状态条。
菜单:
QMenuBar
addMenu
QMenu
addAction
QMenuItem/QAction
构造器
菜单的响应
状态条
ServerSocket.cpp
ThAccept.h
ThAccept.cpp
ThClient.h
ThClient.cpp
ServerWindow.h
ServerWindow.cpp
ChatServer.cpp
chatServer.cpp 主程序
chatServer.pro
QT实现的界面
网络的数据通信
服务器端
建立用户UI
建立服务器socket
接受客户连接
为每个各户建立线程处理客户数据
分析设计的一般规律:
1.用例
2.事件流
3.找对象,并且抽象类
4.设计类本身
5.设计类关系(泛化关系,关联关系)
6.设计模式优化设计
设计界面
QMainWindow增加:菜单,工具条,状态条。
菜单:
QMenuBar
addMenu
QMenu
addAction
QMenuItem/QAction
构造器
菜单的响应
状态条
QStatusBar
服务器设计图
ServerSocket.h
<span style="font-size:18px;">#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); // 初始化Socket
int accept() throw (ChatException); // 返回客户的文件描述符
};
#endif
</span>
ServerSocket.cpp
<span style="font-size:18px;">#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_addr.s_addr=inet_addr(ip);
addr.sin_port=htons(port);
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(ChatException)
{
int cfd;
cfd=::accept(fd,NULL,0); // 表明是全局函数
if(cfd==-1) throw ChatException("accept错误");
return cfd;
}
</span>
ThAccept.h
<span style="font-size:18px;">#ifndef TH_ACCEPT_H
#define TH_ACCEPT_H
#include <QThread>
#include "ChatException.h"
#include "ServerSocket.h"
#include <QTextEdit>
class ThAccept : public QThread
{
Q_OBJECT
public:
QTextEdit *info;
private:
ServerSocket server;
public:
void init()throw(ChatException);
void run();//在线程中接收客户连接
public: signals:
void sigInfo(const QString &); // 和append函数保持一致
};
#endif</span>
ThAccept.cpp
<span style="font-size:18px;">#include "ThAccept.h"
#include <cstdio>
#include "ThClient.h"
#include "ServerWindow.h"
using namespace std;
void ThAccept::init()throw(ChatException)
{
sprintf(server.ip,"%s","192.168.180.92");
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::allusers.push_back(th);
connect(th,SIGNAL(sigInfo(const QString&)),
info,SLOT(append(const QString&)));
th->start();
}
catch(ChatException e)
{
//发出信号
emit sigInfo("服务器崩溃!");
break;
}
}
}
</span>
ThClient.h
<span style="font-size:18px;">#ifndef TH_CLIENT_H
#define TH_CLIENT_H
#include <QThread>
class ThClient : public QThread
{
Q_OBJECT
public:
int fd;
public:
void run(); //接收客户数据,广播
public: signals:
void sigInfo(const QString&);
};
#endif
</span>
ThClient.cpp
<span style="font-size:18px;">#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 sigInfo(tr("有客户退出"));
ServerWindow::allusers.remove(this);
close(fd);
//delete this;
break;
}
buf[r]=0;
//发送消息,把接收数据显示到服务器主窗体
emit sigInfo(tr(buf));
//广播
list<ThClient*>::iterator it=
ServerWindow::allusers.begin();
while(it!=ServerWindow::allusers.end())
{
send((*it)->fd,buf,strlen(buf),0);
it++;
}
}
}
</span>
ServerWindow.h
<span style="font-size:18px;">#ifndef SERVER_WINDOW_H
#define SERVER_WINDOW_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 *lbltime; // 显示时间
//接收线程
ThAccept thaccept;
public:
ServerWindow(QWidget*p=NULL);
public slots:
void onStart();
};
#endif
</span>
ServerWindow.cpp
<span style="font-size:18px;">#ifndef SERVER_WINDOW_H
#define SERVER_WINDOW_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 *lbltime; // 显示时间
//接收线程
ThAccept thaccept;
public:
ServerWindow(QWidget*p=NULL);
public slots:
void onStart();
};
#endif
</span>
ChatServer.h
<span style="font-size:18px;">#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
</span>
ChatServer.cpp
<span style="font-size:18px;">#include "ChatException.h"
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
ChatException::ChatException(){
memset(msg,0,sizeof(msg));
sprintf(msg,"聊天异常!");
}
ChatException::ChatException(const char*m){
memset(msg,0,sizeof(msg));
sprintf(msg,"聊天异常:%s!",m);
}
const char* ChatException::what() const throw(){
return msg;
}
</span>
chatServer.cpp 主程序
<span style="font-size:18px;">#include <QApplication>
#include <QTextCodec>
#include "ServerWindow.h"
int main(int args,char**argv)
{
QApplication app(args,argv);
QTextCodec *codec=
QTextCodec::codecForName("gb2312");
QTextCodec::setCodecForTr(codec);
ServerWindow sw;
return app.exec();
}<span style="color:#ff0000;">
</span></span>
chatServer.pro
<span style="font-size:18px;">TEMPLATE=app
SOURCES=chatServer.cpp \
ServerWindow.cpp \
ChatException.cpp \
ServerSocket.cpp \
ThAccept.cpp \
ThClient.cpp
HEADERS=ServerWindow.h \
ChatException.h \
ServerSocket.h \
ThAccept.h \
ThClient.h
CONFIG=release qt
QT=core gui
TARGET=server
</span>