目录
项目背景成品展示
项目简介需求分析客户端功能性需求服务端功能性需求
功能分解实现MsgPool类 存储用户发送的信息ChatServer类 服务端处理ChatClient类 客户端处理UserInfo类 用户信息UserManager类 用户管理loginConnect类 保存TCP socketChatWindow类 用户绘制边框
开发环境项目问题源码链接
项目背景
如今各种各样的聊天工具层出不穷,功能繁多,想通过自己能力,实现一个简单的群聊工具。
成品展示
如果不想要用户列表旁边的数字 则在ChatWindow类中 将RunUserList函数的for循环中 将 +std::to_string(UserList.size())去掉即可
项目简介
Linux下的群聊系统,TCP进行账号的注册与登陆,UDP进行信息的群发。运用CS模型
需求分析
客户端功能性需求
1.完成用户注册,登陆请求发送
2.将用户发送的信息发送到服务端
3.获取当在线用户的信息
服务端功能性需求
1.获取客户端发送信息
2.定义生产线程与消费线程
3.实现用户注册登陆
4.生成数据存在数据池
5.从数据池获取数据进行群发
功能分解实现
MsgPool类 存储用户发送的信息
数据池:用于存储用户发送的信息
线程安全的队列 + 2个接口
线程安全:
同步:条件变量
互斥:互斥锁
队列:
STL::queue
MsgPool()
~MsgPool()
Public
:
void PushMsgToPool(std
::string
& msg
);
void PopMsgFromPool(std
::string
* msg
);
Private
:
bool IsFull()
Private
:
std
::queue
<std
::string
> MsgQue_
;
size_t capacity_
;
pthread_mutex_t MsgQueLock_
;
pthread_cond_t SynComQue_
;
pthread_cond_t SynProQue_
;
ChatServer类 服务端处理
private:
static void* ProducetMsgStart(void* arg
);
内部调用
RevMsg()接收信息
static void* ConsumeMsgStart(void* arg
);
内部调用
BroadcastMsg()群发信息
void RevMsg()
void BroadcastMsg()
void SendMsg(const std
::string
& msg
, struct sockaddr_in
& cliaddr
, socklen_t
& len
)
private:
int UdpSock_
;
int UdpPort
;
Msgpool
* MsgPool_
;
int TcpSock_
;
int TcpPort_
;
userManager
* UserMana_
;
}
ChatClient类 客户端处理
#客户端
注册标识——
>注册请求——
>服务端
登录标识——
>登陆请求——
>服务端
退出登录表识——
>退出登录请求——
>服务端
ChatClient
{
ChatClient(std
::string SvrIp
= “
192.168.79.128”
)
~ChatClient()
void Init()
bool Connect2Server()
bool Register()
bool Login()
bool SendMsg(const std
::string
& msg
)
bool RecvMsg(std
::string
* msg
)
MySelf
& GetMySelf()
void PushUser(std
::string
& user_info
)
std
::vector
<std
::string
>& GetOnlieUser()
private:
int UdpSock_
;
int UdpPort_
;
int TcpSock_
;
int TcpPort_
;
std
::string StrIp_
;
MySelf me_
;
std
::vector
<std
::string
> OnlineUser
;
}
struct MySelf
{
std
::string NiceName_
;
std
::string School_
;
std
::string Passed_
;
uint_t UserId_
;
}
UserInfo类 用户信息
保存用户NickName. School. udp客户端信息。用户状态
public:
UserInfo(const std
::string
& NickName
, const std
::string
& School
, const uint32_t UserId
, const std
::string
& Passed
);
void SetUserStatus(void Status
);
std
::string
& GetPasswd();
int& GetUserStatus();
void SetCliAddr(const struct sockaddr_in
& CliAddrInfo
);
void SetCliAddrLen(const socklen_t
& CliAddrlen
);
Private
:
std
::string NickName_
;
std
::string School_
;
uint_32_t UserId_
;
std
::string Passed_
;
struct sockaddr_in CliAddr_
;
socklen_t CliAdddren_
;
int UserStatus_
;
UserManager类 用户管理
用户管理类:保存在线用户信息和注册用户信息。要分配的用户id
UserManager
{
UserManager();
~UserManager();
int Register(const std
::string
& NickName
, const std
::string
& School
, const std
::string
& Passed
, uint32_t* UserId
);
int Login(const uint32_t& UserId
, const std
::string
& Passed
);
int LoginOut();
bool IsLogin(uint32_t UserId
, const struct sockaddr_in
& cliudp
, const socklen_t
& cliaddrlen
);
void GetOnlineUserInfo(std
::vector
<UserInfo
>* vectorized
);
private:
std
::unordered_map
<uint32_t, UserInfo
> UserMap_
;
pthread_mutex_t Lock_
;
std
::vector
<UserInfo
> OnlineUserVec_
;
uint32_t PerpareUserId_
;
}
loginConnect类 保存TCP socket
用于保存链接的tcp sock 和 chatserver指针
并将注册 用户状态等信息的结构体放入这个文件中
Struct RegInfo
{
char NiceName_
[15];
char School_
[20];
char Passed_
[20];
}
struct LoginInfo
{
uint32_t UserId_
;
char Passed_
[20];
}
enum UserStatus
{
REGFAILED
=0,
REGISTERED
,
LOGINFAILED
,
LOGINED
};
struct ReplyInfo
{
int status
;
uint32_t UserId_
;
}
Public
:
LoginConnect(int sock
, void* server
)
int GetTcpSock()
void* GetServer()
Private
:
int Sock_
;
void* Server_
;
ChatWindow类 用户绘制边框
public:
ChatWindow()
~ChatWindow()
void DrawHeader()
void DrawOutput()
void DrawUserList()
void DrawInput()
void PutStringToWin(WINDOW
* win
, int y
, int x
, const std
::string
& msg
)
void GetStringFromWin(WINDOW
* win
, std
::string
* Data
)
static void RunHeader(ChatWindow
* cw
)
static void RunOutput(ChatWindow
* cw
, ChatClient
* cc
)
static void RunInput(ChatWindow
* cw
, ChatClient
* cc
)
static void RunUserList(ChatWindow
* cw
, ChatClient
* cc
)
static void* DrawWindow(void* arg
)
void Start(ChatClient
* chatcli
)
private:
WINDOW
* header_
;
WINDOW
* output_
;
WINDOW
* input_
;
WINDOW
* user_list_
;
std
::vector
<pthread_t
> threads_
;
pthread_mutex_t lock_
;
开发环境
Linux version 3.10.0-514.el7.x86_64
gcc version 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC)
项目问题
1.互相发送的信息只能是英文,中文则会出现乱码问题
2.项目中没有对退出进行编写,所以右侧人栏则没有人退出之后减少现象
3.数据存储在服务端,并未存储在数据库中,服务端退出则所有数据消失
4.只能生成一个群聊房,无法开启多个
源码链接
位于Gitee上的源码链接 位于GitHub上的源码链接