结构化数据传输
server
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <Windows.h>
#include <WinSock2.h>
using namespace std
;
#pragma comment(lib,"ws2_32.lib")
struct DataPackage
{
int age
;
char name
[32];
};
int main()
{
WORD ver
= MAKEWORD(2, 2);
WSADATA dat
;
WSAStartup(ver
, &dat
);
SOCKET _sock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
sockaddr_in _sin
= {};
_sin
.sin_family
= AF_INET
;
_sin
.sin_port
= htons(4567);
_sin
.sin_addr
.S_un
.S_addr
= inet_addr("127.0.0.1");
if (bind(_sock
, (sockaddr
*)&_sin
, sizeof(_sin
)) == SOCKET_ERROR
)
{
cout
<< "绑定用于接收客户端连接的网络端口失败" << endl
;
}
else {
cout
<< "绑定网络端口成功..." << endl
;
}
if (listen(_sock
, 5) == SOCKET_ERROR
)
{
cout
<< "监听网络端口失败..." << endl
;
}
else {
cout
<< "监听网络端口成功..." << endl
;
}
sockaddr_in clientAddr
= {};
int nAddrLen
= sizeof(sockaddr_in
);
SOCKET _cSock
= INVALID_SOCKET
;
_cSock
= accept(_sock
, (sockaddr
*)&clientAddr
, &nAddrLen
);
if (_cSock
== INVALID_SOCKET
)
{
cout
<< "错误,接收到无效客户端SOCKET..." << endl
;
}
else
{
cout
<< "接收数据客户端有效..." << endl
;
}
cout
<< "新客户端加入:socket = " << _cSock
<< ", IP = " << inet_ntoa(clientAddr
.sin_addr
) << endl
;
char _recvBuf
[128] = {};
while (true)
{
int nLen
= recv(_cSock
, _recvBuf
, 128, 0);
if (nLen
<= 0)
{
cout
<< "客户端已退出,任务结束" << endl
;
break;
}
cout
<< "收到命令:" << _recvBuf
<< endl
;
if (strcmp(_recvBuf
, "getInfo") == 0) {
DataPackage dp
= {80,"张国荣"};
send(_cSock
, (const char*)&dp
, sizeof(DataPackage
), 0);
}
else {
char msgBuf
[] = "hello ,I'm server!";
send(_cSock
, msgBuf
, strlen(msgBuf
) + 1, 0);
}
}
closesocket(_sock
);
WSACleanup();
getchar();
return 0;
}
client
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <Windows.h>
#include <WinSock2.h>
using namespace std
;
#pragma comment(lib,"ws2_32.lib")
struct DataPackage
{
int age
;
char name
[32];
};
int main()
{
WORD ver
= MAKEWORD(2, 2);
WSADATA dat
;
WSAStartup(ver
, &dat
);
SOCKET _sock
= socket(AF_INET
, SOCK_STREAM
, 0);
if (_sock
== INVALID_SOCKET
)
{
cout
<< "连接服务器失败..." << endl
;
}
else {
cout
<< "连接服务器成功.." << endl
;
}
sockaddr_in _sin
= {};
_sin
.sin_family
= AF_INET
;
_sin
.sin_port
= htons(4567);
_sin
.sin_addr
.S_un
.S_addr
= inet_addr("127.0.0.1");
int ret
= connect(_sock
, (sockaddr
*)(&_sin
), sizeof(sockaddr_in
));
if (ret
== SOCKET_ERROR
)
{
cout
<< "连接服务器失败" << endl
;
}
else {
cout
<< "连接服务器成功" << endl
;
}
while (true)
{
char cmdBuf
[128] = {};
scanf("%s", cmdBuf
);
if (strcmp(cmdBuf
, "exit") == 0) {
cout
<< "已退出客户端,任务结束!" << endl
;
break;
}
else {
send(_sock
, cmdBuf
, strlen(cmdBuf
) + 1, 0);
}
char recBuf
[256] = {};
int nlen
= recv(_sock
, recBuf
, 256, 0);
if (nlen
> 0) {
DataPackage
*dp
= (DataPackage
*)recBuf
;
cout
<< "接受的数据为:age: " << dp
->age
<< ", name: "<< dp
->name
<< endl
;
}
else {
cout
<< "接受数据失败" << endl
;
}
}
closesocket(_sock
);
WSACleanup();
getchar();
return 0;
}
以上命名格式输入错误的时,强制类型转换带来的不安全;
2. 网络数据报文
* 报文有两个部分,包头和包体,是网络消息的基本单元;
* 包头:描述本次消息包的大小,描述数据的作用;
*包体:数据;
2.1 server
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <Windows.h>
#include <WinSock2.h>
using namespace std
;
#pragma comment(lib,"ws2_32.lib")
enum CMD
{
CMD_LOGIN
,
CMD_LOGOUT
,
LOG_ERROR
};
struct DataHeader
{
short dataLength
;
short cmd
;
};
struct Login
{
char userName
[32];
char PassWord
[32];
};
struct LoginResult
{
int result
;
};
struct LogOut
{
char userName
[32];
};
struct LogOutResult
{
int result
;
};
int main()
{
WORD ver
= MAKEWORD(2, 2);
WSADATA dat
;
WSAStartup(ver
, &dat
);
SOCKET _sock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
sockaddr_in _sin
= {};
_sin
.sin_family
= AF_INET
;
_sin
.sin_port
= htons(4567);
_sin
.sin_addr
.S_un
.S_addr
= inet_addr("127.0.0.1");
if (bind(_sock
, (sockaddr
*)&_sin
, sizeof(_sin
)) == SOCKET_ERROR
)
{
cout
<< "绑定用于接收客户端连接的网络端口失败" << endl
;
}
else {
cout
<< "绑定网络端口成功..." << endl
;
}
if (listen(_sock
, 5) == SOCKET_ERROR
)
{
cout
<< "监听网络端口失败..." << endl
;
}
else {
cout
<< "监听网络端口成功..." << endl
;
}
sockaddr_in clientAddr
= {};
int nAddrLen
= sizeof(sockaddr_in
);
SOCKET _cSock
= INVALID_SOCKET
;
_cSock
= accept(_sock
, (sockaddr
*)&clientAddr
, &nAddrLen
);
if (_cSock
== INVALID_SOCKET
)
{
cout
<< "错误,接收到无效客户端SOCKET..." << endl
;
}
else
{
cout
<< "接收数据客户端有效..." << endl
;
}
cout
<< "新客户端加入: socket = " << _cSock
<< ", IP = " << inet_ntoa(clientAddr
.sin_addr
) << endl
;
while (true)
{
DataHeader header
= {};
int nLen
= recv(_cSock
,(char*)&header
, sizeof(DataHeader
), 0);
if (nLen
<= 0)
{
cout
<< "客户端已退出,任务结束" << endl
;
break;
}
cout
<< "收到命令:数据命令:" << header
.cmd
<< ",数据长度:"<< header
.dataLength
<< endl
;
switch (header
.cmd
) {
case CMD_LOGIN
:
{
Login login
= {};
recv(_cSock
, (char*)&login
, sizeof(Login
), 0);
LoginResult ret
= {1};
send(_cSock
, (char*)&header
, sizeof(DataHeader
), 0);
send(_cSock
, (char*)&ret
, sizeof(LoginResult
), 0);
}
break;
case CMD_LOGOUT
:
{
LogOut logOut
= {};
recv(_cSock
, (char*)&logOut
, sizeof(LogOut
), 0);
LogOutResult ret
= { 1 };
send(_cSock
, (char*)&header
, sizeof(DataHeader
), 0);
send(_cSock
, (char*)&ret
, sizeof(LogOutResult
), 0);
}
break;
default:
{
header
.cmd
= LOG_ERROR
;
header
.dataLength
= 0;
send(_cSock
, (char *)&header
, sizeof(header
), 0);
break;
}
}
}
closesocket(_sock
);
WSACleanup();
getchar();
return 0;
}
2.2 client
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <Windows.h>
#include <WinSock2.h>
using namespace std
;
#pragma comment(lib,"ws2_32.lib")
enum CMD
{
CMD_LOGIN
,
CMD_LOGOUT
,
LOG_ERROR
};
struct DataHeader
{
short dataLength
;
short cmd
;
};
struct Login
{
char userName
[32];
char PassWord
[32];
};
struct LoginResult
{
int result
;
};
struct LogOut
{
char userName
[32];
};
struct LogOutResult
{
int result
;
};
int main()
{
WORD ver
= MAKEWORD(2, 2);
WSADATA dat
;
WSAStartup(ver
, &dat
);
SOCKET _sock
= socket(AF_INET
, SOCK_STREAM
, 0);
if (_sock
== INVALID_SOCKET
)
{
cout
<< "连接服务器失败..." << endl
;
}
else {
cout
<< "连接服务器成功.." << endl
;
}
sockaddr_in _sin
= {};
_sin
.sin_family
= AF_INET
;
_sin
.sin_port
= htons(4567);
_sin
.sin_addr
.S_un
.S_addr
= inet_addr("127.0.0.1");
int ret
= connect(_sock
, (sockaddr
*)(&_sin
), sizeof(sockaddr_in
));
if (ret
== SOCKET_ERROR
)
{
cout
<< "连接服务器失败" << endl
;
}
else {
cout
<< "连接服务器成功" << endl
;
}
while (true)
{
char cmdBuf
[128] = {};
scanf("%s", cmdBuf
);
if (strcmp(cmdBuf
, "exit") == 0) {
cout
<< "已退出客户端,任务结束!" << endl
;
break;
}
else if (strcmp(cmdBuf
, "login") == 0) {
Login login
= { "jmm","lovely" };
DataHeader dh
= {sizeof(login
),CMD_LOGIN
};
send(_sock
, (char*)&dh
, sizeof(dh
), 0);
send(_sock
, (char *)&login
, sizeof(login
), 0);
DataHeader retHeader
= {};
LoginResult loginRet
= {};
recv(_sock
, (char*)&retHeader
, sizeof(retHeader
), 0);
recv(_sock
, (char*)&loginRet
, sizeof(loginRet
), 0);
cout
<< "LoginResult: " << loginRet
.result
<< endl
;
}
else if (strcmp(cmdBuf
, "logout") == 0) {
LogOut logout
= {};
DataHeader dh
= {sizeof(logout
),CMD_LOGOUT
};
send(_sock
, (char *)&dh
, sizeof(dh
), 0);
send(_sock
, (char *)&logout
, sizeof(logout
), 0);
DataHeader retHeader
= {};
LoginResult logoutRet
= {};
recv(_sock
, (char*)&retHeader
, sizeof(retHeader
), 0);
recv(_sock
, (char*)&logoutRet
, sizeof(logoutRet
), 0);
cout
<< "LogOutResult: " << logoutRet
.result
<< endl
;
}
else {
cout
<< "不支持该命令,请重新输入!" << endl
;
}
}
closesocket(_sock
);
WSACleanup();
getchar();
return 0;
}
2.3 运行结果
转载请注明原文地址: https://mac.8miu.com/read-506664.html