#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#ifdef _WIN32
#include<windows.h>
#include<WinSock2.h>
#else
#include<unistd.h>
#include<arpa/inet.h>
#include<string.h>
#define SOCKET int
#define INVALID_SOCKET (int)(~0)
#define SOCKET_ERROR (-1)
#endif
#include<stdio.h>
#include<thread>
//指令
enum CMD
{
CMD_LOGIN,
CMD_LOGIN_RESULT,
CMD_LOGINOUT,
CMD_LOGINOUT_RESULT,
CMD_NEW_USER_JOIN,
CMD_ERROR
};
//消息头
struct DataHeader
{
short dataLength;
short cmd;
};
//登录
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 Loginout : public DataHeader
{
Loginout()
{
dataLength = sizeof(Loginout);
cmd = CMD_LOGINOUT;
}
char userName[32];
};
//登出结果
struct LoginoutResult : public DataHeader
{
LoginoutResult()
{
dataLength = sizeof(LoginoutResult);
cmd = CMD_LOGINOUT_RESULT;
result = 0;
}
int result;
};
struct NewUserJoin : public DataHeader
{
NewUserJoin()
{
dataLength = sizeof(NewUserJoin);
cmd = CMD_NEW_USER_JOIN;
sock = 0;
}
int sock;
};
//处理请求函数
int processor(SOCKET _cSock)
{
char szRecv[1024] = { };
int nLen = recv(_cSock, szRecv, sizeof(DataHeader), 0);
// 5 接收客户端数据
//将数据放在缓冲区中,缓冲区大小为1024
//首先判断消息头
DataHeader* header = (DataHeader*)szRecv;
if (nLen <= 0)
{
printf("与服务器断开连接,任务结束。\n");
return -1;
}
// 6 处理请求
switch (header->cmd)
{
case CMD_LOGIN_RESULT:
{
recv(_cSock, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
LoginResult* loginRet = (LoginResult*)szRecv;
printf("收到服务端消息:CMD_LOGIN_Result,数据长度 : %d\n", loginRet->dataLength);
}
break;
case CMD_LOGINOUT_RESULT:
{
recv(_cSock, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
LoginoutResult* loginout = (LoginoutResult*)szRecv;
printf("收到服务端消息:CMD_LOGINOUT_Result,数据长度 : %d\n", loginout->dataLength);
}
break;
case CMD_NEW_USER_JOIN:
{
recv(_cSock, szRecv + sizeof(DataHeader), header->dataLength - sizeof(DataHeader), 0);
NewUserJoin* userJoin = (NewUserJoin*)szRecv;
printf("收到服务端消息:CMD_NEW_USER_JOIN,数据长度 : %d\n", userJoin->dataLength);
}
break;
}
}
bool g_bRun = true;
void cmdThread(SOCKET _sock)
{
while (true)
{
char cmdBuf[256] = { };
scanf("%s", cmdBuf);
if (0 == strcmp(cmdBuf, "exit"))
{
printf("退出cmdThread线程\n");
g_bRun = false;
break;
}
else if (0 == strcmp(cmdBuf, "login"))
{
Login login;
strcpy(login.userName, "yql");
strcpy(login.PassWord, "yqlyyds");
send(_sock, (const char*)&login, sizeof(login), 0);
}
else if (0 == strcmp(cmdBuf, "loginout"))
{
Loginout loginout;
strcpy(loginout.userName, "yql");
send(_sock, (const char*)&loginout, sizeof(loginout), 0);
}
else {
printf("不支持的命令,请重新输入。\n");
}
}
}
int main()
{
#ifdef _WIN32
WORD ver = MAKEWORD(2, 2); //创建WINDOWS版本号
WSADATA dat;
WSAStartup(ver, &dat); //启动网络环境,此函数调用了一个WINDOWS的静态链接库,因此需要加入静态链接库文件
#endif
//-----------------
//-- 用socket API建立简易TCP客户端
// 1 建立一个socket
SOCKET _sock = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == _sock)
{
printf("错误,建立Socket失败...\n");
}
else {
printf("建立Socket成功...\n");
}
// 2 连接服务器 connect
sockaddr_in _sin = { };
_sin.sin_family = AF_INET;
_sin.sin_port = htons(4567);
#ifdef _WIN32
_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
#else
_sin.sin_addr.s_addr = inet_addr("192.168.43.1");
#endif
int ret = connect(_sock, (sockaddr*)&_sin, sizeof(sockaddr_in));
if (ret == SOCKET_ERROR)
{
printf("错误,连接失败...\n");
}
else {
printf("连接成功...\n");
}
//启动线程
std::thread t1(cmdThread, _sock);
//分离主线程和子线程
t1.detach();
while (g_bRun)
{
fd_set fdRead;
fd_set fdWrite;
fd_set fdExc;
//清空
FD_ZERO(&fdRead);
FD_ZERO(&fdWrite);
FD_ZERO(&fdExc);
//将描述符存入数组
FD_SET(_sock, &fdRead);
FD_SET(_sock, &fdWrite);
FD_SET(_sock, &fdExc);
timeval t = { 1,0 };
int ret = select(_sock, &fdRead, 0, 0, &t);
if (ret < 0)
{
printf("select任务结束1\n");
break;
}
if (FD_ISSET(_sock, &fdRead))
{
FD_CLR(_sock, &fdRead);
if (-1 == processor(_sock))
{
printf("select任务结束2\n");
break;
}
}
//printf("空闲时间处理其他业务...\n");
}
// 7 关闭套接字 closesocket
#ifdef _WIN32
closesocket(_sock);
//-----------------
//清除Windows socket环境
WSACleanup(); //关闭Socket网络环境
#else
close(_sock);
#endif
printf("已退出,任务结束...\n");
getchar();
return 0;
}
03-07
1028
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)