私聊,群聊,查看在线好友,文件导入,日志导出 (MFC+Socket)
vs2019
void CServerDlg::OnBnClickedBtnStartStop()
{
// TODO: 在此添加控件通知处理程序代码
if (m_srvrStatus=="已停止") //状态为已停止,则要开启服务器监听端口
{
UpdateData();
CString log=_T("服务器已开启,等待客户端连接......");
m_ctrlChatRoomInfo.AddString(log);
WCHAR str[3];
m_ctrlMaxCnt.GetWindowTextW(str,3);//将最大客户端数 那个下拉窗口当前的数,拷贝到str中
m_maxClient=_ttoi(str);//将str从String转换到int
if (m_listenPort<1024)
{
MessageBox(_T("请选择大于1024的端口!"),_T("提示"),MB_ICONWARNING);
return;
}
if (!m_serverSocket.Create(m_listenPort))
{
MessageBox(_T("创建套接字出错!"),_T("错误"),MB_ICONERROR);
return;
}
if (!m_serverSocket.Listen())
{
MessageBox(_T("监听失败!"),_T("错误"),MB_ICONERROR);
return;
}
GetDlgItem(IDC_BTN_START_STOP)->SetWindowTextW(_T("停止"));
GetDlgItem(IDC_LISTENPORT)->EnableWindow(FALSE);
}
else //状态为正在监听,要停止监听
{
CString log = _T("服务器已关闭!!");
m_ctrlChatRoomInfo.AddString(log);
GetDlgItem(IDC_BTN_START_STOP)->SetWindowTextW(_T("启动"));
GetDlgItem(IDC_LISTENPORT)->EnableWindow(TRUE);
m_clientCnt = 0;
vector<CClientSocket *>::iterator iter;
for (iter = clientList.begin(); iter != clientList.end(); )
{
unsigned char buf[2]={
0};
buf[0]=SERVERCLOSE;
(*iter)->Send(buf,1);
(*iter)->Close();
delete (*iter);
iter=clientList.erase(iter);
}
clientList.clear();
m_serverSocket.Close();//关闭服务端套接字
}
m_srvrStatus=m_srvrStatus=="正在监听……"?"已停止":"正在监听……";
GetDlgItem(IDC_STATUS)->SetWindowTextW(m_srvrStatus);
UpdateData(FALSE);
}
void CServerDlg::ProcessData(CClientSocket *clientSocket)
{
unsigned char buf[MAX_BUFSIZE] = {
0 };
wchar_t wbuf[MAX_BUFSIZE] = {
0 };
wchar_t srcName[16] = {
0 }, dstName[16] = {
0 };
int len = clientSocket->Receive(buf, MAX_BUFSIZE);
vector<CClientSocket *>::iterator iter;
vector<CString>::iterator file_iter;//文件列表
CString log, usrName, usrNP, usrLove, usrAge, usrSex;
CTime tm;
bool undefine = true;//判断是否注册或是密码正确
CString data_c_srcName;
unsigned char data_buf[MAX_BUFSIZE] = {
0 };
CString strPath;
char CH_nameLength = NULL;
int IN_namelength = 0;
unsigned int strName_length = 0;
char chName_length;
string temp;
ifstream fin("user.txt", ios::in);//在这个路径下读入文件
ofstream fout("user.txt", ios::app);//在同一个路径下,如果注册成功则写入文件
switch (buf[0])
{
case NEWCLIENT: //收到用户要登录的消息
memcpy(wbuf, buf + 1, 16); //获取用户名
usrName = wbuf;
memcpy(wbuf, buf + 1, len - 1); //获取用户名和密码
usrNP = wbuf;
clientSocket->m_userName = usrName; //设置用户名
while (std::getline(fin, temp))//每次读一行的数据进入temp中。
{
if (usrNP == temp.c_str()) //用户名和密码都正确
{
undefine = false;
break;
}
}
fin.close();
if (undefine)
{
buf[0] = ERROR;
clientSocket->Send(buf, 1); //用户未注册或密码不正确
return;
}
for (iter = clientList.begin(); iter < clientList.end(); iter++)
{
if (*iter != NULL)
{
(*iter)->Send(buf, 17); //转发到每个客户端
}
}
Sleep(100);
for (iter = clientList.begin(); iter < clientList.end() - 1; iter++)
{
if (*iter != NULL)
{
buf[0] = ONLINECLIENT;
memcpy(wbuf, (*iter)->m_userName.GetBuffer(0), (*iter)->m_userName.GetLength() * 2);
memcpy(buf + 1, wbuf, (*iter)->m_userName.GetLength() * 2);
clientSocket->Send(buf, (*iter)->m_userName.GetLength() * 2 + 1);
Sleep(100);
}
}
break;
case REGISTER://注册
memcpy(wbuf, buf + 1, 16); //获取用户名
usrName = wbuf;
memcpy(wbuf, buf + 1, len - 1); //获取用户名和密码
usrNP = wbuf;
clientSocket->m_usrNP = usrNP; //设置用户名和密码
clientSocket->m_userName = usrName; //设置用户名
//判断用户是否注册过
while (std::getline(fin, temp))//每次读一行的数据进入temp中。
{
temp = temp.substr(0,8);
if (usrName == temp.c_str()) //用户注册过
{
undefine = false;
buf[0] = HADDEFINED;
clientSocket->Send(buf, 1); //用户已注册过
return;
}
}
if (undefine)
{
this->m_ctrlUsers.AddString(usrNP);
temp = CT2A(usrNP.GetBuffer());
fout << temp << endl;//向文件写入注册者的用户名,然后换一行
fout.close();
buf[0] = REGISTER;
clientSocket->Send(buf, 1); //注册用户
UpdateData(false);
return;
}
break;
case MESSAGE_ALL: //群发
for (iter = clientList.begin(); iter < clientList.end(); iter++)
{
if (*iter != NULL)
{
(*iter)->Send(buf, len);
}
}
break;
case MESSAGE_ONE: //私聊
memcpy(dstName, buf + 1, 16);
memcpy(srcName, buf + 17, 16);
for (iter = clientList.begin(); iter < clientList.end(); iter++)
{
if ((*iter)->m_userName == dstName) //发给目的用户
{
(*iter)->Send(buf, len);
break;
}
}
break;
case EXIT: //断开连接的代码
tm = CTime::GetCurrentTime();
log.Format(_T("【%s : %u】与服务器断开。"), clientSocket->m_userIP, clientSocket->m_userPort);
log = tm.Format("%Y-%m-%d %X : ") + log;
m_ctrlChatRoomInfo.AddString(log);
m_clientCnt--;
UpdateData(FALSE);
clientSocket->Close();
for (iter = clientList.begin(); iter != clientList.end();)
{
if (*iter == clientSocket) //连接断开,删除套接字
{
iter = clientList.erase(iter);
}
else //给其他客户端转发下线的消息
{
(*iter)->Send(buf, len);
iter++;
}
}
delete clientSocket;
break;
default:
break;
}
}
void CClientDlg::OnBnClickedBtnConnect()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItem(IDC_BTN_CONNECT)->GetWindowTextW(str);
if (str == "连接服务器") //当前处于断开状态
{
UpdateData();
if (!m_clientSocket.Create()) //建立Socket
{
MessageBox(_T("创建套接字失败!"),_T("错误"),MB_ICONERROR);
return;
}
if (!m_clientSocket.Connect(_T("127.0.0.1"),2537))
{
MessageBox(_T("连接服务器失败,请稍候重试!"),_T("错误"),MB_ICONERROR);
m_clientSocket.Close();
return;
}
GetDlgItem(IDC_BTN_CONNECT)->SetWindowTextW(_T("断开连接"));
m_publicChannel += _T("【系统消息】成功连接服务器!");
m_publicChannel += _T("\r\n");
UpdateData(false);
}
else //当前处于连接状态
{
UpdateData();
unsigned char buf[MAX_BUFSIZE];
buf[0] = EXIT; //断开连接
memcpy(buf+1,m_usrName.GetBuffer(0),m_usrName.GetLength()*2);
m_clientSocket.Send(buf,m_usrName.GetLength()*2+1); //退出用户的用户名
m_clientSocket.Close();
GetDlgItem(IDC_BTN_CONNECT)->SetWindowTextW(_T("连接服务器"));
GetDlgItem(IDC_USERNAME)->EnableWindow(TRUE); //断开后可以改用户名
GetDlgItem(IDC_EDIT1)->EnableWindow(TRUE); //断开后可以改密码
m_ctrlUserOnline.ResetContent(); //清空在线用户列表
GetDlgItem(IDC_BUTTON1)->EnableWindow(true); //断开后可再点击登录
GetDlgItem(IDC_BUTTON2)->EnableWindow(true); //断开后可以再点击注册
m_publicChannel += _T("【系统消息】成功断开服务器!");
m_publicChannel += _T("\r\n");
m_publicChannel += _T("【系统消息】");
m_publicChannel += m_usrName;
m_publicChannel += _T("被强制下线!\r\n");
UpdateData(false);
}
}
//注册
void CClientDlg::OnRegister()
{
// TODO: 在此添加控件通知处理程序代码
if (m_clientSocket.m_hSocket == INVALID_SOCKET)
{
MessageBox(_T("未连接到服务器!"), _T("错误"), MB_ICONERROR);
return;
}
else
{
UpdateData();
if (m_usrName.IsEmpty()||m_usrPassword.IsEmpty())
{
MessageBox(_T("请输入用户名/密码!"), _T("提示"), MB_ICONWARNING);
GetDlgItem(IDC_USERNAME)->SetFocus();
return;
}
if (m_usrName.GetLength()!=8)
{
MessageBox(_T("用户名不等于8位"), _T("提示"), MB_ICONWARNING);
GetDlgItem(IDC_USERNAME)->SetFocus();
return;
}
else
{
unsigned char buf[MAX_BUFSIZE];
buf[0] = REGISTER;
m_usrNP = m_usrName + m_usrPassword;
memcpy(buf + 1, m_usrNP.GetBuffer(0), m_usrNP.GetLength() * 2);
m_clientSocket.Send(buf, m_usrNP.GetLength() * 2 + 1);
GetDlgItem(IDC_USERNAME)->EnableWindow(FALSE); //登陆后后不可更改用户名
}
}
}
//登录
void CClientDlg::OnLogoIn()
{
// TODO: 在此添加控件通知处理程序代码
if (m_clientSocket.m_hSocket == INVALID_SOCKET)
{
MessageBox(_T("未连接到服务器!"), _T("错误"), MB_ICONERROR);
return;
}
else
{
UpdateData();
if (m_usrName.IsEmpty()||m_usrPassword.IsEmpty())
{
MessageBox(_T("请输入用户名/密码!"), _T("提示"), MB_ICONWARNING);
GetDlgItem(IDC_USERNAME)->SetFocus();
return;
}
unsigned char buf[MAX_BUFSIZE];
buf[0] = NEWCLIENT;
m_usrNP = m_usrName + m_usrPassword;
//m_usrNP +=m_usrPassword;
memcpy(buf + 1, m_usrNP.GetBuffer(0), m_usrNP.GetLength() * 2);
m_clientSocket.Send(buf, m_usrNP.GetLength() * 2 + 1);
GetDlgItem(IDC_USERNAME)->EnableWindow(FALSE); //登陆后后不可更改用户名
GetDlgItem(IDC_EDIT1)->EnableWindow(FALSE); //登陆后后不可更改密码
GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE); //登陆后后不可再点击登录
GetDlgItem(IDC_BUTTON2)->EnableWindow(false); //登陆后不可以再点击注册
}
}
*客户端的事件处理
void CClientDlg::ProcessRecvData()
{
CString str;
unsigned char buf[MAX_BUFSIZE]={
0};
int len = m_clientSocket.Receive(buf,MAX_BUFSIZE);
wchar_t msg[MAX_BUFSIZE]={
0};//消息内容
wchar_t usrName[MAX_BUFSIZE]={
0};//用户名字
wchar_t srcName[16] = {
0};
//接收文件列表
char CH_nameLength = NULL;
int IN_namelength = 0;
srand((unsigned int)time(NULL));
if (NEWCLIENT == buf[0]) //新用户上线消息
{
memcpy(usrName, buf + 1, len-1); //用户名
if (LB_ERR == m_ctrlUserOnline.FindString(-1,usrName)) //在线用户增加
{
m_ctrlUserOnline.AddString(usrName);
}
if (LB_ERR == m_ctrlPeopleToTalk.FindString(-1,usrName)) //可以私聊的人增加
{
m_ctrlPeopleToTalk.AddString(usrName);
}
str.Empty();
str+=_T("【系统消息】\"");
str+=usrName;
str+=_T("\"进入到聊天室\r\n");
m_publicChannel+=str;
}
else if (ONLINECLIENT == buf[0]) //当前在线用户信息
{
memcpy(usrName,buf+1,len-1); //用户名
if (LB_ERR == m_ctrlUserOnline.FindString(-1,usrName))
{
m_ctrlUserOnline.AddString(usrName);
}
if (LB_ERR == m_ctrlPeopleToTalk.FindString(-1,usrName))
{
m_ctrlPeopleToTalk.AddString(usrName);
}
}
else if (MESSAGE_ALL == buf[0]) //公共频道的消息
{
str.Empty();
memcpy(usrName,buf+1,16);
memcpy(msg,buf+27,len-27);
str+=_T("\"");
str+=usrName;
str+=_T("\"");
//str+=style;
str+=_T("对 \"所有人\"说:");
str+=msg;
m_publicChannel+=str;
m_publicChannel+=_T("\r\n");
}
else if (MESSAGE_ONE == buf[0]) //私聊
{
wchar_t srcUsrName[16]={
0},dstUsrName[16]={
0};
memcpy(dstUsrName,buf+1,16); //目的用户名
memcpy(srcUsrName,buf+17,16); //源用户名
memcpy(msg,buf+43,len-43); //消息内容
str.Empty();
if (m_usrName == dstUsrName)
{
str+=_T("\"");
str+=srcUsrName;
str+=_T("\"");
str+=_T("对 \"你\"说:");
str+=msg;
m_privateChannel+=str;
m_privateChannel+=_T("\r\n");
}
}
else if (EXIT == buf[0]) //离开的信息
{
memcpy(usrName,buf+1,len-1); //用户名
m_ctrlUserOnline.AddString(usrName);
str.Empty();
str+=_T("【系统消息】\"");
str+=usrName;
str+=_T("\"离开聊天室!\r\n");
m_publicChannel+=str;
int n=m_ctrlUserOnline.FindString(-1,usrName);
if (LB_ERR != n)
{
m_ctrlUserOnline.DeleteString((UINT)n);
m_ctrlUserOnline.DeleteString((UINT)n);
}
n=m_ctrlPeopleToTalk.FindString(-1,usrName);
if (LB_ERR != n)
{
m_ctrlPeopleToTalk.DeleteString((UINT)n);
}
}
else if (SERVERCLOSE == buf[0]) //服务器关闭消息
{
MessageBox(_T("服务器已关闭!"),_T("提示"),MB_ICONINFORMATION);
m_clientSocket.Close();
GetDlgItem(IDC_BTN_CONNECT)->SetWindowTextW(_T("连接服务器"));
GetDlgItem(IDC_USERNAME)->EnableWindow(TRUE); //断开后可以改用户名
m_ctrlUserOnline.ResetContent();
}
else if (REPEATNAME == buf[0])
{
MessageBox(_T("用户名已存在,请重试!"),_T("提示"),MB_ICONINFORMATION);
m_clientSocket.Close();
GetDlgItem(IDC_BTN_CONNECT)->SetWindowTextW(_T("连接服务器"));
GetDlgItem(IDC_USERNAME)->EnableWindow(TRUE); //断开后可以改用户名
m_ctrlUserOnline.ResetContent();
GetDlgItem(IDC_BUTTON1)->EnableWindow(TRUE); //可再点击登录
GetDlgItem(IDC_BUTTON2)->EnableWindow(TRUE); //可以再点击注册
}
else if (ERROR == buf[0])
{
MessageBox(_T("用户名或密码不正确,请重试!"), _T("提示"), MB_ICONINFORMATION);
GetDlgItem(IDC_USERNAME)->EnableWindow(TRUE); //断开后可以改用户名
m_ctrlUserOnline.ResetContent();
GetDlgItem(IDC_BUTTON1)->EnableWindow(TRUE); //可再点击登录
GetDlgItem(IDC_BUTTON2)->EnableWindow(TRUE); //可以再点击注册
}
else if (HADDEFINED == buf[0])
{
MessageBox(_T("用户名已被注册!"), _T("提示"), MB_ICONINFORMATION);
GetDlgItem(IDC_USERNAME)->EnableWindow(TRUE); //断开后可以改用户名
m_ctrlUserOnline.ResetContent();
GetDlgItem(IDC_BUTTON1)->EnableWindow(TRUE); //可再点击登录
GetDlgItem(IDC_BUTTON2)->EnableWindow(TRUE); //可以再点击注册
}
else if (REGISTER == buf[0])
{
MessageBox(_T("注册成功!"), _T("提示"), MB_ICONINFORMATION);
}
UpdateData(FALSE);
}
链接: https://pan.baidu.com/s/1ausANhj_W_Wc53GAH7IKwQ
提取码:7vki .