在前面几次的代码里面,因为没有采用面向对象编程的方法,所以代码看起来比较混乱,这次我们采用面向对象编程封装出TcpServer类和TcpClient类
TcpClient类声明:
#ifndef _TCPCLIENT_H_
#define _TCPCLIENT_H_
#include <WinSock2.h>
#include <Windows.h>
#pragma comment(lib, "ws2_32.lib")
enum CMD
{
CMD_LOGIN,
CMD_LogOut,
CMD_LOGIN_SU,
CMD_LOGOUT_SU,
CMD_NEW_USER,
CMD_ERROR
};
struct DataHeader
{
int lenth;
int cmd;
};
// Data Package
struct Login : public DataHeader
{
Login()
{
lenth = sizeof(Login);
cmd = CMD_LOGIN;
}
char UserName[32];
char passWord[32];
};
struct LoginSucceed : public DataHeader
{
LoginSucceed()
{
lenth = sizeof(LoginSucceed);
cmd = CMD_LOGIN_SU;
result = 0;
}
int result;
};
struct LogOut : public DataHeader
{
LogOut()
{
lenth = sizeof(LogOut);
cmd = CMD_LogOut;
}
char UserName[32];
};
struct LogOutSucceed : public DataHeader
{
LogOutSucceed()
{
lenth = sizeof(LogOutSucceed);
cmd = CMD_LOGOUT_SU;
result = 0;
}
int result;
};
struct NewUser : public DataHeader
{
NewUser()
{
lenth = sizeof(NewUser);
cmd = CMD_NEW_USER;
sock = 0;
}
int sock;
};
class TcpClient
{
public:
TcpClient();
//初始化socket
void initSocket();
//连接服务器
int Connect(const char* ip, unsigned short port);
//关闭socket
void Close();
//查询网络消息
bool onRun();
int recvData();
//判断是否在工作中
bool isRun();
//响应网络消息
void onNetMsg(DataHeader* cmdBuf);
//发送数据
int sendData(DataHeader* header);
virtual ~TcpClient();
private:
SOCKET sock = INVALID_SOCKET;
};
#endif // !_TCPCLIENT_H_
TcpServer类声明:
#ifndef _TCPSERVER_H_
#define _TCPSERVER_H_
#define WIN32_LEAN_AND_MEAN
#include <vector>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
using std::vector;
enum CMD
{
CMD_LOGIN,
CMD_LogOut,
CMD_LOGIN_SU,
CMD_LOGOUT_SU,
CMD_NEW_USER,
CMD_ERROR
};
struct DataHeader
{
int lenth;
int cmd;
};
// Data Package
struct Login : public DataHeader
{
Login()
{
lenth = sizeof(Login);
cmd = CMD_LOGIN;
}
char UserName[32] = "";
char passWord[32] = "";
};
struct LoginSucceed : public DataHeader
{
LoginSucceed()
{
lenth = sizeof(LoginSucceed);
cmd = CMD_LOGIN_SU;
result = 0;
}
int result;
};
struct LogOut : public DataHeader
{
LogOut()
{
lenth = sizeof(LogOut);
cmd = CMD_LogOut;
}
char UserName[32] = "";
};
struct LogOutSucceed : public DataHeader
{
LogOutSucceed()
{
lenth = sizeof(LogOutSucceed);
cmd = CMD_LOGOUT_SU;
result = 0;
}
int result;
};
struct NewUser : public DataHeader
{
NewUser()
{
lenth = sizeof(NewUser);
cmd = CMD_NEW_USER;
sock = 0;
}
int sock;
};
class TcpServer
{
public:
TcpServer();
virtual ~TcpServer();
//初始化socket
SOCKET initSocket();
//绑定端口号
int Bind(const char* ip, unsigned short port);
//监听端口号
int Listen(int n);
//接收客户端连接
SOCKET Accept();
//关闭socket
void Close();
//处理网络消息
bool onRun();
//是否工作中
bool isRun();
//接收数据
int recvData(SOCKET cSock);
//响应网络消息
virtual void onNetMsg(SOCKET cSock, DataHeader* cmdBuf);
//给指定socket发送数据
int sendData(SOCKET cSock, DataHeader* header);
void sendDataToAll(DataHeader* header);
private:
SOCKET sock;
vector<SOCKET>clients;
};
#endif // !_TCPSERVER_H_
在编程过程中,我们还可以将消息结构声明在一个 .h 文件中,这样在需要时,只需包含头文件即可,提高代码复用率
另外,本次代码即以前代码全部上传至Gitee,需要这自行下载: