Sever.cpp
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <WinSock2.h>
#include <stdio.h>
#include <map>
#include <string>
#include <vector>
using namespace std;
string user[2] = { "lyh0", "lyh1" };
string pwd[2] = { "lyh0", "lyh1" };
string chat[2] = { "Hello!", "Hi!" };
vector<string> loginusr;
//存放socket的数组
vector<SOCKET> g_clients;
enum cmd
{
cmd_login,
cmd_login_result,
cmd_logout,
cmd_logout_result,
cmd_new_user_join,
cmd_chat,
cmd_error
};
//数据包头
struct DataHeader
{
short datalength;
short cmd;
};
//可以用下面的这种写法,但是不利于衍生成更复杂的消息。
//struct Login
//{
// DataHeader dataheader;
// char username[32];
// char password[32];
//};
//用继承的方式将报头和报体放在一起发送
struct Login : public DataHeader
{
//在构造函数里面初始化
Login()
{
datalength = sizeof(Login);
cmd = cmd_login;
}
char username[32];
char password[32];
};
struct Loginresult : public DataHeader
{
Loginresult()
{
datalength = sizeof(Loginresult);
cmd = cmd_login_result;
result = 0;
}
int result;
};
struct Logout : public DataHeader
{
Logout()
{
datalength = sizeof(Logout);
cmd = cmd_logout;
}
char username[32];
};
struct Logoutresult : public DataHeader
{
Logoutresult()
{
datalength = sizeof(Logoutresult);
cmd = cmd_logout_result;
result = 0;
}
int result;
};
struct Message : public DataHeader
{
Message()
{
datalength = sizeof(Message);
cmd = cmd_chat;
}
char message[256];
};
struct Messageret : public DataHeader
{
Messageret()
{
datalength = sizeof(Messageret);
cmd = cmd_chat;
}
char messageret[256];
};
struct Newuserjoin : public DataHeader
{
Newuserjoin()
{
datalength = sizeof(Newuserjoin);
cmd = cmd_new_user_join;
}
int socketid;
};
//把处理请求的逻辑写成一个函数
int Process(SOCKET _clientSock)
{
//用缓冲区接受数据
char recvBuf[1024] = {};
DataHeader* header = (DataHeader*)recvBuf;
//5.1. recv 接收客户端发送的数据
int nlen = recv(_clientSock, recvBuf, sizeof(DataHeader), 0);
if (nlen <= 0)
{
printf("Client %d exit!\n", (int)_clientSock);
return -1;
}
//5.2 send 处理请求, 向客户端发送数据, 用switch判断命令
switch (header->cmd)
{
case cmd_login:
{
//接受客户端输入的账号密码
//使用datalength获取数据
recv(_clientSock, recvBuf + sizeof(DataHeader), header->datalength - sizeof(DataHeader), 0);
Login* login = (Login*)recvBuf;
printf("receive cmd from <Socket: %d>, cmd: cmd_login.\n", (int)_clientSock);
Loginresult result;
//防止重复登录
if (0 != loginusr.size())
{
for (int i = 0; i < (int)loginusr.size(); i++)
{
if (loginusr[i] == string(login->username))
{
result.result = 2;
}
}
if (2 == result.result)
{
send(_clientSock, (char*)&result, sizeof(Loginresult), 0);
return 1;
}
}
//判断用户名与密码是否正确的过程
for (int i = 0; i < 2; i++)
{
if (user[i] == string(login->username))
{
if (pwd[i] == string(login->password))
{
loginusr.push_back(user[i]);
printf("it is %d users connect now.\n", (int)loginusr.size());
result.result = 1;
send(_clientSock, (char*)&result, sizeof(Loginresult), 0);
return 1;
}
else
{
result.result = 0;
send(_clientSock, (char*)&result, sizeof(Loginresult), 0);
return 1;
}
}
}
send(_clientSock, (char*)&result, sizeof(Loginresult), 0);
}
break;
case cmd_logout:
{
recv(_clientSock, recvBuf + sizeof(DataHeader), header->datalength - sizeof(DataHeader), 0);
Logout* logout = (Logout*)recvBuf;
Logoutresult result;
//判断用户名是否正确,且用户在已登录的名单中
for (int i = 0; i < (int)loginusr.size(); i++)